mirror of https://git.wuffs.org/MWCC
2487 lines
70 KiB
C
2487 lines
70 KiB
C
#include "compiler/CPrepTokenizer.h"
|
|
#include "compiler/CError.h"
|
|
#include "compiler/CInt64.h"
|
|
#include "compiler/CMachine.h"
|
|
#include "compiler/CParser.h"
|
|
#include "compiler/CPrep.h"
|
|
#include "compiler/CompilerTools.h"
|
|
#include "compiler/InlineAsmPPC.h"
|
|
#include "compiler/tokens.h"
|
|
#include "cos.h"
|
|
|
|
static Boolean prepnextstringchar_foundnl;
|
|
|
|
short prepskipnextchar(void) {
|
|
short c;
|
|
StringPtr start;
|
|
StringPtr p;
|
|
|
|
start = (StringPtr) pos;
|
|
p = (StringPtr) pos;
|
|
|
|
loop:
|
|
switch ((c = *p)) {
|
|
case 0:
|
|
if (tokenstacklevel > 0 || p >= (StringPtr) prep_file_end) {
|
|
pos = (char *) p;
|
|
nextcharpos = (char *) p;
|
|
return c;
|
|
} else {
|
|
pos = (char *) p++;
|
|
nextcharpos = (char *) p;
|
|
return c;
|
|
}
|
|
case 4:
|
|
case 5:
|
|
p++;
|
|
goto loop;
|
|
case ' ':
|
|
case '\t':
|
|
case '\n':
|
|
case '\v':
|
|
case '\f':
|
|
spaceskip = 1;
|
|
p++;
|
|
goto loop;
|
|
case ';':
|
|
pos = (char *) p++;
|
|
if (tokenstacklevel <= 0 && in_assembler && copts.asmsemicolcomment) {
|
|
spaceskip = 1;
|
|
nextcharpos = (char *) CPrep_SkipNewComment(p);
|
|
return CPrep_SkipNewCommentChar;
|
|
}
|
|
nextcharpos = (char *) p;
|
|
return c;
|
|
case '#':
|
|
pos = (char *) p++;
|
|
if (tokenstacklevel <= 0 && in_assembler && copts.asmpoundcomment) {
|
|
spaceskip = 1;
|
|
nextcharpos = (char *) CPrep_SkipNewComment(p);
|
|
return CPrep_SkipNewCommentChar;
|
|
}
|
|
nextcharpos = (char *) p;
|
|
return c;
|
|
case '/':
|
|
pos = (char *) p++;
|
|
if (copts.multibyteaware) {
|
|
while (p[0] == '\\' && !COS_IsMultiByte(start, p) && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
} else {
|
|
while (p[0] == '\\' && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
}
|
|
if (tokenstacklevel <= 0) {
|
|
if (p[0] == '/' && (!copts.ANSIstrict || copts.cplusplus || copts.c9x)) {
|
|
spaceskip = 1;
|
|
nextcharpos = (char *) CPrep_SkipNewComment(p + 1);
|
|
return CPrep_SkipNewCommentChar;
|
|
} else if (p[0] == '*') {
|
|
spaceskip = 1;
|
|
p++;
|
|
for (;;) {
|
|
if (!(c = *(p++))) {
|
|
if (tokenstacklevel > 0 || p >= (StringPtr) prep_file_end) {
|
|
CPrep_Error(CErrorStr103);
|
|
nextcharpos = (char *) p - 1;
|
|
return c;
|
|
}
|
|
p[-1] = ' ';
|
|
}
|
|
if (c == '*') {
|
|
if (copts.multibyteaware) {
|
|
while (p[0] == '\\' && !COS_IsMultiByte(start, p) && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
} else {
|
|
while (p[0] == '\\' && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
}
|
|
if (*p == '/') {
|
|
p++;
|
|
goto loop;
|
|
}
|
|
}
|
|
if (c == '\r')
|
|
foundnl();
|
|
}
|
|
}
|
|
}
|
|
nextcharpos = (char *) p;
|
|
return c;
|
|
case '%':
|
|
pos = (char *) p++;
|
|
if (*p == ':' && copts.cplusplus) {
|
|
nextcharpos = (char *) p + 1;
|
|
return '#';
|
|
}
|
|
nextcharpos = (char *) p;
|
|
return c;
|
|
case '\\':
|
|
pos = (char *) p++;
|
|
mid_backslash:
|
|
if (*p == '\r') {
|
|
if (!copts.multibyteaware || !COS_IsMultiByte(start, p - 1)) {
|
|
foundnl();
|
|
if (p[1] == '\n')
|
|
p += 2;
|
|
else
|
|
p += 1;
|
|
goto loop;
|
|
}
|
|
}
|
|
nextcharpos = (char *) p;
|
|
return c;
|
|
case '?':
|
|
pos = (char *) p++;
|
|
if (copts.trigraphs && p[0] == '?') {
|
|
switch (p[1]) {
|
|
case '=':
|
|
nextcharpos = (char *) p + 2;
|
|
return '#';
|
|
case '/':
|
|
c = '\\';
|
|
p += 2;
|
|
goto mid_backslash;
|
|
case '\'':
|
|
nextcharpos = (char *) p + 2;
|
|
return '^';
|
|
case '(':
|
|
nextcharpos = (char *) p + 2;
|
|
return '[';
|
|
case ')':
|
|
nextcharpos = (char *) p + 2;
|
|
return ']';
|
|
case '!':
|
|
nextcharpos = (char *) p + 2;
|
|
return '|';
|
|
case '<':
|
|
nextcharpos = (char *) p + 2;
|
|
return '{';
|
|
case '>':
|
|
nextcharpos = (char *) p + 2;
|
|
return '}';
|
|
case '-':
|
|
nextcharpos = (char *) p + 2;
|
|
return '~';
|
|
}
|
|
}
|
|
nextcharpos = (char *) p;
|
|
return c;
|
|
default:
|
|
pos = (char *) p++;
|
|
nextcharpos = (char *) p;
|
|
return c;
|
|
}
|
|
}
|
|
|
|
short prepnextchar(void) {
|
|
short c;
|
|
StringPtr start;
|
|
StringPtr p;
|
|
|
|
start = (StringPtr) pos;
|
|
p = (StringPtr) pos;
|
|
|
|
loop:
|
|
switch ((c = *(p++))) {
|
|
case 0:
|
|
pos = (char *) p - 1;
|
|
return c;
|
|
case '/':
|
|
if (copts.multibyteaware) {
|
|
while (p[0] == '\\' && !COS_IsMultiByte(start, p) && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
} else {
|
|
while (p[0] == '\\' && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
}
|
|
if (p[0] == '/' && (!copts.ANSIstrict || copts.cplusplus)) {
|
|
spaceskip = 1;
|
|
pos = (char *) CPrep_SkipNewComment(p + 1);
|
|
return CPrep_SkipNewCommentChar;
|
|
} else if (p[0] == '*') {
|
|
spaceskip = 1;
|
|
p++;
|
|
for (;;) {
|
|
if (!(c = *(p++))) {
|
|
if (tokenstacklevel > 0 || p >= (StringPtr) prep_file_end) {
|
|
pos = (char *) p - 1;
|
|
CPrep_Error(CErrorStr103);
|
|
return c;
|
|
}
|
|
p[-1] = ' ';
|
|
}
|
|
if (c == '*') {
|
|
if (copts.multibyteaware) {
|
|
while (p[0] == '\\' && !COS_IsMultiByte(start, p) && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
} else {
|
|
while (p[0] == '\\' && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
}
|
|
if (*p == '/')
|
|
break;
|
|
}
|
|
if (c == '\r')
|
|
foundnl();
|
|
}
|
|
pos = (char *) p + 1;
|
|
return ' ';
|
|
} else {
|
|
pos = (char *) p;
|
|
return c;
|
|
}
|
|
case '\\':
|
|
backslash:
|
|
if (*p == '\r') {
|
|
if (!copts.multibyteaware || !COS_IsMultiByte(start, p - 1)) {
|
|
foundnl();
|
|
if (p[1] == '\n')
|
|
p += 2;
|
|
else
|
|
p += 1;
|
|
goto loop;
|
|
}
|
|
}
|
|
pos = (char *) p;
|
|
return c;
|
|
case '%':
|
|
if (*p == ':' && copts.cplusplus) {
|
|
pos = (char *) p + 1;
|
|
return '#';
|
|
}
|
|
pos = (char *) p;
|
|
return c;
|
|
case '?':
|
|
if (copts.trigraphs && p[0] == '?') {
|
|
switch (p[1]) {
|
|
case '=':
|
|
pos = (char *) p + 2;
|
|
return '#';
|
|
case '/':
|
|
c = '\\';
|
|
p += 2;
|
|
goto backslash;
|
|
case '\'':
|
|
pos = (char *) p + 2;
|
|
return '^';
|
|
case '(':
|
|
pos = (char *) p + 2;
|
|
return '[';
|
|
case ')':
|
|
pos = (char *) p + 2;
|
|
return ']';
|
|
case '!':
|
|
pos = (char *) p + 2;
|
|
return '|';
|
|
case '<':
|
|
pos = (char *) p + 2;
|
|
return '{';
|
|
case '>':
|
|
pos = (char *) p + 2;
|
|
return '}';
|
|
case '-':
|
|
pos = (char *) p + 2;
|
|
return '~';
|
|
}
|
|
}
|
|
pos = (char *) p;
|
|
return c;
|
|
default:
|
|
pos = (char *) p;
|
|
return c;
|
|
}
|
|
}
|
|
|
|
short prepnextstringchar(StringPtr str, Boolean flag) {
|
|
StringPtr p;
|
|
short c;
|
|
|
|
p = (StringPtr) pos;
|
|
|
|
loop:
|
|
switch ((c = *(p++))) {
|
|
case 0:
|
|
pos = (char *) p - 1;
|
|
return c;
|
|
case '\\':
|
|
backslash:
|
|
if (p[0] == '\r' && (!copts.multibyteaware || !COS_IsMultiByte(str, p - 1))) {
|
|
if (flag)
|
|
foundnl();
|
|
else
|
|
prepnextstringchar_foundnl = 1;
|
|
if (p[1] == '\n')
|
|
p += 2;
|
|
else
|
|
p += 1;
|
|
goto loop;
|
|
}
|
|
pos = (char *) p;
|
|
return c;
|
|
case '?':
|
|
if (copts.trigraphs && p[0] == '?') {
|
|
switch (p[1]) {
|
|
case '=':
|
|
pos = (char *) p + 2;
|
|
return '#';
|
|
case '/':
|
|
c = '\\';
|
|
p += 2;
|
|
goto backslash;
|
|
case '\'':
|
|
pos = (char *) p + 2;
|
|
return '^';
|
|
case '(':
|
|
pos = (char *) p + 2;
|
|
return '[';
|
|
case ')':
|
|
pos = (char *) p + 2;
|
|
return ']';
|
|
case '!':
|
|
pos = (char *) p + 2;
|
|
return '|';
|
|
case '<':
|
|
pos = (char *) p + 2;
|
|
return '{';
|
|
case '>':
|
|
pos = (char *) p + 2;
|
|
return '}';
|
|
case '-':
|
|
pos = (char *) p + 2;
|
|
return '~';
|
|
}
|
|
}
|
|
pos = (char *) p;
|
|
return c;
|
|
default:
|
|
pos = (char *) p;
|
|
return c;
|
|
}
|
|
}
|
|
|
|
void CPrep_MatchChar(char ch, Boolean flag) {
|
|
char *p;
|
|
char *start;
|
|
char c;
|
|
Boolean haveBackslash;
|
|
|
|
p = start = pos;
|
|
haveBackslash = 0;
|
|
|
|
loop:
|
|
if (!(c = *(p++))) {
|
|
if (tokenstacklevel > 0 || p >= prep_file_end)
|
|
CPrep_Error(CErrorStr102);
|
|
else if (ch == '"')
|
|
CPrep_Error(CErrorStr101);
|
|
else if (ch == '\'')
|
|
CPrep_Error(CErrorStr100);
|
|
CPrep_Error(CErrorStr117);
|
|
pos = p - 1;
|
|
return;
|
|
}
|
|
|
|
if (c == '\r') {
|
|
if (!copts.multibyteaware || !COS_IsMultiByte(start, p - 1)) {
|
|
if (flag)
|
|
foundnl();
|
|
if (*p == '\n')
|
|
p++;
|
|
CPrep_Error(CErrorStr112);
|
|
pos = p;
|
|
return;
|
|
}
|
|
haveBackslash = 0;
|
|
goto loop;
|
|
}
|
|
|
|
if (c == '?' && p[0] == '?' && copts.trigraphs) {
|
|
switch (p[1]) {
|
|
case '!':
|
|
case '\'':
|
|
case '(':
|
|
case ')':
|
|
case '-':
|
|
case '<':
|
|
case '=':
|
|
case '>':
|
|
haveBackslash = 0;
|
|
p += 2;
|
|
goto loop;
|
|
case '/':
|
|
p += 2;
|
|
goto backslash;
|
|
}
|
|
}
|
|
|
|
if (c == '\\' && !haveBackslash && (!copts.multibyteaware || !COS_IsMultiByte(start, p - 1))) {
|
|
backslash:
|
|
if (*p == '\r') {
|
|
if (flag)
|
|
foundnl();
|
|
if (*(++p) == '\n')
|
|
p++;
|
|
haveBackslash = 0;
|
|
} else {
|
|
haveBackslash = 1;
|
|
}
|
|
goto loop;
|
|
}
|
|
|
|
if (c == ch && !haveBackslash) {
|
|
pos = p;
|
|
} else {
|
|
haveBackslash = 0;
|
|
goto loop;
|
|
}
|
|
}
|
|
|
|
char *CPrep_MatchChar2(char *start, char ch, Boolean flag) {
|
|
char *p;
|
|
char c;
|
|
Boolean haveBackslash;
|
|
|
|
p = start;
|
|
haveBackslash = 0;
|
|
|
|
loop:
|
|
if (!(c = *(p++))) {
|
|
if (tokenstacklevel > 0 || p >= prep_file_end)
|
|
CPrep_Error(CErrorStr102);
|
|
else if (ch == '"')
|
|
CPrep_Error(CErrorStr101);
|
|
else if (ch == '\'')
|
|
CPrep_Error(CErrorStr100);
|
|
CPrep_Error(CErrorStr117);
|
|
return p - 1;
|
|
}
|
|
|
|
if (c == '\r') {
|
|
if (!copts.multibyteaware || !COS_IsMultiByte(start, p - 1)) {
|
|
if (flag)
|
|
foundnl();
|
|
if (*p == '\n')
|
|
p++;
|
|
CPrep_Error(CErrorStr112);
|
|
return p;
|
|
}
|
|
haveBackslash = 0;
|
|
goto loop;
|
|
}
|
|
|
|
if (c == '?' && p[0] == '?' && copts.trigraphs) {
|
|
switch (p[1]) {
|
|
case '!':
|
|
case '\'':
|
|
case '(':
|
|
case ')':
|
|
case '-':
|
|
case '<':
|
|
case '=':
|
|
case '>':
|
|
haveBackslash = 0;
|
|
p += 2;
|
|
goto loop;
|
|
case '/':
|
|
p += 2;
|
|
goto backslash;
|
|
}
|
|
}
|
|
|
|
if (c == '\\' && !haveBackslash && (!copts.multibyteaware || !COS_IsMultiByte(start, p - 1))) {
|
|
backslash:
|
|
if (*p == '\r') {
|
|
if (flag)
|
|
foundnl();
|
|
if (*(++p) == '\n')
|
|
p++;
|
|
haveBackslash = 0;
|
|
} else {
|
|
haveBackslash = 1;
|
|
}
|
|
goto loop;
|
|
}
|
|
|
|
if (c == ch && !haveBackslash) {
|
|
return p;
|
|
} else {
|
|
haveBackslash = 0;
|
|
goto loop;
|
|
}
|
|
}
|
|
|
|
short prepcurchar(void) {
|
|
char *save_pos;
|
|
short t;
|
|
|
|
save_pos = pos;
|
|
t = prepnextchar();
|
|
nextcharpos = pos;
|
|
pos = save_pos;
|
|
|
|
return t;
|
|
}
|
|
|
|
static short prepcurstringchar(StringPtr str) {
|
|
char *save_pos;
|
|
short t;
|
|
|
|
save_pos = pos;
|
|
prepnextstringchar_foundnl = 0;
|
|
t = prepnextstringchar(str, 0);
|
|
nextcharpos = pos;
|
|
pos = save_pos;
|
|
|
|
return t;
|
|
}
|
|
|
|
static void prepcurstringchar_skip(void) {
|
|
pos = nextcharpos;
|
|
if (prepnextstringchar_foundnl)
|
|
foundnl();
|
|
}
|
|
|
|
char *ReadIdentifier(const char *p) {
|
|
char buf[256];
|
|
const char *start;
|
|
unsigned int ch;
|
|
int len;
|
|
|
|
start = p;
|
|
len = 0;
|
|
for (;;) {
|
|
ch = (unsigned char) *p;
|
|
if (cprep_idarray[ch]) {
|
|
if (len < 255)
|
|
buf[len++] = *p;
|
|
p++;
|
|
} else {
|
|
if (copts.multibyteaware) {
|
|
if ((unsigned char) *p == '\\' && !COS_IsMultiByte(start, p) && p[1] == '\r') {
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
foundnl();
|
|
} else {
|
|
break;
|
|
}
|
|
} else {
|
|
if ((unsigned char) *p == '\\' && p[1] == '\r') {
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
foundnl();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
buf[len] = 0;
|
|
tkidentifier = GetHashNameNodeExport(buf);
|
|
return (char *) p;
|
|
}
|
|
|
|
static short intsuffix(short token, Boolean flag) {
|
|
Boolean is_unsigned;
|
|
Boolean is_long;
|
|
Boolean is_longlong;
|
|
short t;
|
|
|
|
is_unsigned = is_long = is_longlong = 0;
|
|
t = token;
|
|
switch (t) {
|
|
case 'u':
|
|
case 'U':
|
|
is_unsigned = 1;
|
|
pos = nextcharpos;
|
|
t = prepcurchar();
|
|
if (t == 'l' || t == 'L') {
|
|
is_long = 1;
|
|
pos = nextcharpos;
|
|
t = *pos;
|
|
if (copts.longlong) {
|
|
pos = nextcharpos;
|
|
t = prepcurchar();
|
|
if (t == 'l' || t == 'L') {
|
|
is_longlong = 1;
|
|
pos = nextcharpos;
|
|
t = *pos;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 'l':
|
|
case 'L':
|
|
is_long = 1;
|
|
pos = nextcharpos;
|
|
t = prepcurchar();
|
|
if (t == 'u' || t == 'U') {
|
|
is_unsigned = 1;
|
|
pos = nextcharpos;
|
|
t = *pos;
|
|
} else if (copts.longlong && (t == 'l' || t == 'L')) {
|
|
is_longlong = 1;
|
|
pos = nextcharpos;
|
|
t = prepcurchar();
|
|
if (t == 'u' || t == 'U') {
|
|
is_unsigned = 1;
|
|
pos = nextcharpos;
|
|
t = *pos;
|
|
}
|
|
}
|
|
break;
|
|
case 'i':
|
|
case 'I':
|
|
if (copts.cpp_extensions && !copts.ANSIstrict && copts.longlong) {
|
|
pos = nextcharpos;
|
|
t = prepcurchar();
|
|
if (t == '6') {
|
|
pos = nextcharpos;
|
|
t = prepcurchar();
|
|
if (t == '4') {
|
|
is_long = is_longlong = 1;
|
|
pos = nextcharpos;
|
|
t = *pos;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 'b':
|
|
case 'B':
|
|
case 'f':
|
|
case 'F':
|
|
if (InlineAsm_gccmode)
|
|
return IT_INT;
|
|
break;
|
|
}
|
|
|
|
if ((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z') || (t == '_') || (t >= '0' && t <= '9'))
|
|
CPrep_Error(CErrorStr105);
|
|
|
|
if (!is_longlong && !is_long) {
|
|
if (!is_unsigned && CInt64_IsInRange(tkintconst, stsignedint.size))
|
|
return IT_INT;
|
|
if ((flag || is_unsigned) && CInt64_IsInURange(tkintconst, stunsignedint.size))
|
|
return IT_UINT;
|
|
}
|
|
if (!is_longlong) {
|
|
if (!is_unsigned && CInt64_IsInRange(tkintconst, stsignedlong.size))
|
|
return IT_LONG;
|
|
if (CInt64_IsInURange(tkintconst, stunsignedlong.size))
|
|
return IT_ULONG;
|
|
}
|
|
if (copts.longlong) {
|
|
if (!is_unsigned && CInt64_IsInRange(tkintconst, stsignedlonglong.size))
|
|
return IT_LONGLONG;
|
|
if (CInt64_IsInURange(tkintconst, stsignedlonglong.size))
|
|
return IT_ULONGLONG;
|
|
}
|
|
CError_Error(CErrorStr154);
|
|
tkintconst = cint64_zero;
|
|
return IT_INT;
|
|
}
|
|
|
|
static short floatsuffix(short token) {
|
|
short whichtype;
|
|
|
|
switch (token) {
|
|
case 'f':
|
|
case 'F':
|
|
pos = nextcharpos;
|
|
token = *pos;
|
|
whichtype = IT_FLOAT;
|
|
if (stfloat.size != stlongdouble.size)
|
|
tkfloatconst = CMach_CalcFloatConvert((Type *) &stfloat, tkfloatconst);
|
|
break;
|
|
case 'l':
|
|
case 'L':
|
|
pos = nextcharpos;
|
|
token = *pos;
|
|
whichtype = IT_LONGDOUBLE;
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
if (!copts.ANSIstrict) {
|
|
pos = nextcharpos;
|
|
token = *pos;
|
|
whichtype = IT_DOUBLE;
|
|
if (stdouble.size != stlongdouble.size)
|
|
tkfloatconst = CMach_CalcFloatConvert((Type *) &stdouble, tkfloatconst);
|
|
}
|
|
break;
|
|
default:
|
|
if (copts.float_constants) {
|
|
whichtype = IT_FLOAT;
|
|
if (stfloat.size != stlongdouble.size)
|
|
tkfloatconst = CMach_CalcFloatConvert((Type *) &stfloat, tkfloatconst);
|
|
} else {
|
|
whichtype = IT_DOUBLE;
|
|
if (stdouble.size != stlongdouble.size)
|
|
tkfloatconst = CMach_CalcFloatConvert((Type *) &stdouble, tkfloatconst);
|
|
}
|
|
}
|
|
|
|
if ((token >= 'a' && token <= 'z') || (token >= 'A' && token <= 'Z') || (token == '_') || (token >= '0' && token <= '9')) {
|
|
CPrep_Error(CErrorStr105);
|
|
whichtype = IT_DOUBLE;
|
|
}
|
|
|
|
return whichtype;
|
|
}
|
|
|
|
static short tohex(short token) {
|
|
if (token >= '0' && token <= '9')
|
|
return token - '0';
|
|
if (token >= 'a' && token <= 'f')
|
|
return token - 'a' + 10;
|
|
if (token >= 'A' && token <= 'F')
|
|
return token - 'A' + 10;
|
|
return -1;
|
|
}
|
|
|
|
static SInt32 nextchar(StringPtr str) {
|
|
short tmpchr;
|
|
SInt32 chr_max;
|
|
Boolean out_of_bounds;
|
|
SInt32 chr;
|
|
short i;
|
|
short t;
|
|
|
|
chr_max = 0xFF;
|
|
if (widestring) chr_max = 0xFFFF;
|
|
|
|
was_escchar = 0;
|
|
t = prepnextstringchar(str, 1);
|
|
|
|
if (t == '\\' && (!copts.multibyteaware || !COS_IsMultiByte(str, pos - 1))) {
|
|
was_escchar = 1;
|
|
switch ((t = prepnextstringchar(str, 1))) {
|
|
case 'a': return 7;
|
|
case 'b': return 8;
|
|
case 't': return 9;
|
|
case 'v': return 11;
|
|
case 'f': return 12;
|
|
case 'n':
|
|
if (copts.mpwc_newline)
|
|
return 13;
|
|
else
|
|
return 10;
|
|
case 'r':
|
|
if (copts.mpwc_newline)
|
|
return 10;
|
|
else
|
|
return 13;
|
|
case 'e': return 27;
|
|
case 'x':
|
|
chr = tohex(prepnextstringchar(str, 1));
|
|
if (chr == -1) {
|
|
CPrep_Error(CErrorStr100);
|
|
return ' ';
|
|
}
|
|
out_of_bounds = 0;
|
|
while (tohex((tmpchr = prepcurstringchar(str))) != -1) {
|
|
chr = (chr << 4) + tohex(tmpchr);
|
|
prepcurstringchar_skip();
|
|
if (chr & ~chr_max)
|
|
out_of_bounds = 1;
|
|
}
|
|
if (out_of_bounds)
|
|
CError_Error(CErrorStr100);
|
|
break;
|
|
default:
|
|
if (t >= '0' && t <= '7') {
|
|
out_of_bounds = 0;
|
|
i = 1;
|
|
chr = t - '0';
|
|
while (i < 3 && (tmpchr = prepcurstringchar(str)) >= '0' && tmpchr <= '7') {
|
|
chr = (chr << 3) + tmpchr - '0';
|
|
prepcurstringchar_skip();
|
|
if (chr & ~chr_max)
|
|
out_of_bounds = 1;
|
|
i++;
|
|
}
|
|
if (out_of_bounds)
|
|
CError_Error(CErrorStr100);
|
|
} else {
|
|
chr = t;
|
|
}
|
|
}
|
|
} else {
|
|
chr = t;
|
|
}
|
|
|
|
if (chr_max == 0xFF)
|
|
return (char) (chr & chr_max);
|
|
else
|
|
return (chr & chr_max);
|
|
}
|
|
|
|
StringPtr CPrep_SkipNewComment(StringPtr str) {
|
|
StringPtr p;
|
|
|
|
p = str;
|
|
while (1) {
|
|
switch (*(p++)) {
|
|
case 0:
|
|
if (tokenstacklevel > 0 || p >= (StringPtr) prep_file_end) {
|
|
CPrep_SkipNewCommentChar = 0;
|
|
return p - 1;
|
|
}
|
|
p[-1] = ' ';
|
|
continue;
|
|
|
|
case '\r':
|
|
CPrep_SkipNewCommentChar = '\r';
|
|
return p;
|
|
|
|
case '\\':
|
|
if (copts.multibyteaware && COS_IsMultiByte(str, p - 1))
|
|
continue;
|
|
|
|
if (*p == '\r') {
|
|
++p;
|
|
foundnl();
|
|
}
|
|
|
|
if (*p == '\n')
|
|
p++;
|
|
continue;
|
|
|
|
case '"':
|
|
if (InlineAsm_gccmode) {
|
|
CPrep_SkipNewCommentChar = '\r';
|
|
return p - 1;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
Boolean skipendoflinematch(StringPtr str, short token) {
|
|
StringPtr start;
|
|
|
|
start = str - 1;
|
|
pos = (char *) start;
|
|
|
|
while (1) {
|
|
switch (*(str++)) {
|
|
case 0:
|
|
case '\r':
|
|
pos = (char *) str - 1;
|
|
return 0;
|
|
|
|
case '"':
|
|
if (token == '"') {
|
|
pos = (char *) str;
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
case '\'':
|
|
if (token == '\'') {
|
|
pos = (char *) str;
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
case '\\':
|
|
if (copts.multibyteaware && COS_IsMultiByte(start, str - 1))
|
|
continue;
|
|
|
|
switch (*(str++)) {
|
|
case 0:
|
|
pos = (char *) str - 1;
|
|
return 0;
|
|
|
|
case '\r':
|
|
foundnl();
|
|
if (*str == '\n')
|
|
str++;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case '?':
|
|
if (copts.trigraphs && str[0] == '?' && str[1] == '/' && str[2] == '\r') {
|
|
foundnl();
|
|
str += 3;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void skipendofline(void) {
|
|
StringPtr start;
|
|
StringPtr p;
|
|
short ch;
|
|
|
|
start = (StringPtr) pos;
|
|
p = (StringPtr) pos;
|
|
|
|
while (1) {
|
|
switch (*(p++)) {
|
|
case 0:
|
|
case '\r':
|
|
pos = (char *) p - 1;
|
|
return;
|
|
|
|
case '"':
|
|
if (!skipendoflinematch(p, '"'))
|
|
return;
|
|
p = (StringPtr) pos;
|
|
break;
|
|
|
|
case '\'':
|
|
if (!skipendoflinematch(p, '\''))
|
|
return;
|
|
p = (StringPtr) pos;
|
|
break;
|
|
|
|
case '/':
|
|
if (copts.multibyteaware) {
|
|
while (*p == '\\' && !COS_IsMultiByte(start, p) && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
} else {
|
|
while (*p == '\\' && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
}
|
|
|
|
if (*p == '/' && (!copts.ANSIstrict || copts.cplusplus)) {
|
|
// EOL comment
|
|
pos = (char *) CPrep_SkipNewComment(p + 1);
|
|
if (CPrep_SkipNewCommentChar == '\r')
|
|
pos--;
|
|
return;
|
|
}
|
|
|
|
if (*p == '*') {
|
|
// Block comment
|
|
pos = (char *) p - 1;
|
|
spaceskip = 1;
|
|
p++;
|
|
while (1) {
|
|
if ((ch = *(p++)) == 0) {
|
|
if (tokenstacklevel > 0 || p >= (StringPtr) prep_file_end) {
|
|
pos = (char *) p - 1;
|
|
CPrep_Error(CErrorStr103);
|
|
return;
|
|
}
|
|
p[-1] = ' ';
|
|
}
|
|
|
|
if (ch == '*') {
|
|
if (copts.multibyteaware) {
|
|
while (*p == '\\' && !COS_IsMultiByte(start, p) && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
} else {
|
|
while (*p == '\\' && p[1] == '\r') {
|
|
foundnl();
|
|
if (p[2] == '\n')
|
|
p += 3;
|
|
else
|
|
p += 2;
|
|
}
|
|
}
|
|
|
|
if (*p == '/') {
|
|
p++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ch == '\r')
|
|
foundnl();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case '\\':
|
|
if (copts.multibyteaware && COS_IsMultiByte(start, p - 1))
|
|
continue;
|
|
|
|
if (*p == '\r') {
|
|
foundnl();
|
|
if (p[1] == '\n')
|
|
p += 2;
|
|
else
|
|
p += 1;
|
|
}
|
|
break;
|
|
|
|
case '?':
|
|
if (copts.trigraphs && p[0] == '?' && p[1] == '/' && p[2] == '\r') {
|
|
foundnl();
|
|
p += 3;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CPrep_SkipAsmComment(void) {
|
|
Boolean save_macrocheck = macrocheck;
|
|
skipendofline();
|
|
macrocheck = save_macrocheck;
|
|
}
|
|
|
|
static short tille(void) { return TK_ILLEGAL; }
|
|
|
|
static short tcret(void) {
|
|
newline();
|
|
if (cprep_eoltokens)
|
|
return TK_EOL;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static short tapos(short _t) {
|
|
int t;
|
|
int t2;
|
|
int i;
|
|
StringPtr start;
|
|
UInt32 maxvalue;
|
|
int bytecount;
|
|
CInt64 newBits;
|
|
CInt64 val;
|
|
|
|
start = (StringPtr) pos;
|
|
t = nextchar((StringPtr) pos);
|
|
if ((t == '\'' || t == 0 || t == '\r') && !was_escchar) {
|
|
CPrep_Error(CErrorStr100);
|
|
tkintconst = cint64_zero;
|
|
tksize = IT_INT;
|
|
return TK_INTCONST;
|
|
}
|
|
|
|
t2 = nextchar(start);
|
|
if (t2 == '\'' && !was_escchar) {
|
|
if (widestring) {
|
|
switch (stwchar.size) {
|
|
case 1:
|
|
CInt64_SetULong(&tkintconst, (UInt8) t);
|
|
tksize = copts.cplusplus ? IT_SCHAR : IT_INT;
|
|
break;
|
|
case 2:
|
|
CInt64_SetULong(&tkintconst, (UInt16) t);
|
|
tksize = IT_UINT;
|
|
break;
|
|
case 4:
|
|
CInt64_SetULong(&tkintconst, (UInt32) t);
|
|
tksize = IT_UINT;
|
|
break;
|
|
default:
|
|
CError_FATAL(1386);
|
|
}
|
|
} else {
|
|
if (copts.unsigned_char)
|
|
t &= 0xFF;
|
|
CInt64_SetLong(&tkintconst, t);
|
|
tksize = copts.cplusplus ? IT_SCHAR : IT_INT;
|
|
}
|
|
} else {
|
|
if (widestring) {
|
|
switch (stwchar.size) {
|
|
case 1:
|
|
CInt64_SetULong(&val, 8);
|
|
maxvalue = 0xFF;
|
|
bytecount = 1;
|
|
break;
|
|
case 2:
|
|
CInt64_SetULong(&val, 16);
|
|
maxvalue = 0xFFFF;
|
|
bytecount = 2;
|
|
break;
|
|
case 4:
|
|
CInt64_SetULong(&val, 32);
|
|
maxvalue = 0xFFFFFFFF;
|
|
bytecount = 4;
|
|
break;
|
|
default:
|
|
CError_FATAL(1424);
|
|
}
|
|
} else {
|
|
CInt64_SetULong(&val, 8);
|
|
maxvalue = 0xFF;
|
|
bytecount = 1;
|
|
}
|
|
|
|
CInt64_SetULong(&tkintconst, t & maxvalue);
|
|
i = bytecount;
|
|
|
|
while (1) {
|
|
if ((t2 == 0 || t2 == '\r') && !was_escchar) {
|
|
CPrep_Error(CErrorStr100);
|
|
break;
|
|
}
|
|
|
|
CInt64_SetULong(&newBits, t2 & maxvalue);
|
|
tkintconst = CInt64_Or(CInt64_Shl(tkintconst, val), newBits);
|
|
i += bytecount;
|
|
|
|
t2 = nextchar(start);
|
|
if (t2 == '\'' && !was_escchar)
|
|
break;
|
|
|
|
if (i >= stunsignedlonglong.size) {
|
|
CPrep_Error(CErrorStr100);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i <= stunsignedint.size && stunsignedint.size < stunsignedlong.size)
|
|
tksize = IT_UINT;
|
|
else if (i <= stunsignedlong.size)
|
|
tksize = IT_ULONG;
|
|
else
|
|
tksize = IT_ULONGLONG;
|
|
}
|
|
|
|
return TK_INTCONST;
|
|
}
|
|
|
|
static short tquot(short t) {
|
|
Type *type;
|
|
StringPtr string_ptr;
|
|
SInt32 size;
|
|
short c;
|
|
StringPtr save_pos;
|
|
StringPtr start_pos;
|
|
CInt64 ch64;
|
|
|
|
start_pos = (StringPtr) pos;
|
|
at_linestart = 0;
|
|
if (cprep_nostring)
|
|
return '"';
|
|
|
|
string_ptr = (StringPtr) *stringmem;
|
|
ispascalstring = 0;
|
|
size = 0;
|
|
if (widestring)
|
|
type = TYPE(&stwchar);
|
|
else
|
|
type = TYPE(&stchar);
|
|
|
|
if (prepcurstringchar(start_pos) == '\\') {
|
|
save_pos = (StringPtr) pos;
|
|
prepcurstringchar_skip();
|
|
if (prepcurstringchar(start_pos) == 'p') {
|
|
prepcurstringchar_skip();
|
|
ispascalstring = 1;
|
|
string_ptr += type->size;
|
|
} else {
|
|
pos = (char *) save_pos;
|
|
}
|
|
}
|
|
|
|
while (1) {
|
|
c = nextchar(start_pos);
|
|
if ((c == '"' || c == '\r' || c == 0) && !was_escchar) {
|
|
if (c == 0 && (tokenstacklevel > 0 || pos >= prep_file_end))
|
|
CPrep_Error(CErrorStr102);
|
|
else if (c != '"')
|
|
CPrep_Error(CErrorStr101);
|
|
break;
|
|
}
|
|
if ((size + type->size) >= maxstringsize) {
|
|
SInt32 offset = string_ptr - (StringPtr) *stringmem;
|
|
if (!COS_ResizeHandle(stringmem, maxstringsize += 256))
|
|
CError_NoMem();
|
|
string_ptr = (StringPtr) *stringmem + offset;
|
|
}
|
|
if (type->size != 1) {
|
|
CInt64_SetLong(&ch64, c);
|
|
CMach_InitIntMem(type, ch64, string_ptr);
|
|
string_ptr += type->size;
|
|
size += type->size;
|
|
} else {
|
|
*string_ptr = c;
|
|
string_ptr++;
|
|
size++;
|
|
}
|
|
}
|
|
|
|
if (ispascalstring) {
|
|
if (size > 255 && type->size == 1) {
|
|
CPrep_Error(CErrorStr106);
|
|
size = 255;
|
|
}
|
|
CInt64_SetLong(&ch64, size / type->size);
|
|
CMach_InitIntMem(type, ch64, *stringmem);
|
|
size += type->size;
|
|
} else {
|
|
if ((size + 1) >= maxstringsize) {
|
|
if (!COS_ResizeHandle(stringmem, maxstringsize += 256))
|
|
CError_NoMem();
|
|
}
|
|
CMach_InitIntMem(type, cint64_zero, *stringmem + size);
|
|
size += type->size;
|
|
}
|
|
|
|
tksize = size;
|
|
tkstring = galloc(size);
|
|
memcpy(tkstring, *stringmem, tksize);
|
|
|
|
if (widestring)
|
|
c = TK_STRING_WIDE;
|
|
else
|
|
c = TK_STRING;
|
|
return (short) c;
|
|
}
|
|
|
|
static short thash(void) {
|
|
if (at_linestart) {
|
|
preprocessor();
|
|
return 0;
|
|
}
|
|
return '#';
|
|
}
|
|
|
|
static short tmult(void) {
|
|
at_linestart = 0;
|
|
if (prepcurchar() == '=') {
|
|
pos = nextcharpos;
|
|
return TK_MULT_ASSIGN;
|
|
}
|
|
return '*';
|
|
}
|
|
|
|
static short tcolo(void) {
|
|
char t2;
|
|
at_linestart = 0;
|
|
if (copts.cplusplus) {
|
|
t2 = prepcurchar();
|
|
if (t2 == ':') {
|
|
pos = nextcharpos;
|
|
return TK_COLON_COLON;
|
|
}
|
|
if (t2 == '>' && !preprocessing_only) {
|
|
pos = nextcharpos;
|
|
return ']';
|
|
}
|
|
}
|
|
return ':';
|
|
}
|
|
|
|
static short tless(void) {
|
|
short t2;
|
|
at_linestart = 0;
|
|
t2 = prepcurchar();
|
|
if (t2 == '=') {
|
|
pos = nextcharpos;
|
|
return TK_LESS_EQUAL;
|
|
}
|
|
if (t2 == '<') {
|
|
pos = nextcharpos;
|
|
if (prepcurchar() == '=') {
|
|
pos = nextcharpos;
|
|
return TK_SHL_ASSIGN;
|
|
} else {
|
|
return TK_SHL;
|
|
}
|
|
}
|
|
if (t2 == '%' && copts.cplusplus && !preprocessing_only) {
|
|
pos = nextcharpos;
|
|
return '{';
|
|
}
|
|
if (t2 == ':' && copts.cplusplus && !preprocessing_only) {
|
|
pos = nextcharpos;
|
|
return '[';
|
|
}
|
|
return '<';
|
|
}
|
|
|
|
static short tequa(short) {
|
|
at_linestart = 0;
|
|
if (prepcurchar() == '=') {
|
|
pos = nextcharpos;
|
|
return TK_LOGICAL_EQ;
|
|
}
|
|
return '=';
|
|
}
|
|
|
|
static short tgrea(short) {
|
|
short t2;
|
|
at_linestart = 0;
|
|
t2 = prepcurchar();
|
|
if (t2 == '=') {
|
|
pos = nextcharpos;
|
|
return TK_GREATER_EQUAL;
|
|
}
|
|
if (t2 == '>') {
|
|
pos = nextcharpos;
|
|
if (prepcurchar() == '=') {
|
|
pos = nextcharpos;
|
|
return TK_SHR_ASSIGN;
|
|
} else {
|
|
return TK_SHR;
|
|
}
|
|
}
|
|
return '>';
|
|
}
|
|
|
|
static short tatsg(short) {
|
|
char save_idarray;
|
|
char *start_pos = pos;
|
|
|
|
at_linestart = 0;
|
|
|
|
if (copts.objective_c || in_assembler) {
|
|
save_idarray = cprep_idarray['@'];
|
|
cprep_idarray['@'] = 1;
|
|
pos = ReadIdentifier(start_pos - 1);
|
|
cprep_idarray['@'] = save_idarray;
|
|
|
|
if (copts.objective_c) {
|
|
if (!strcmp("@interface", tkidentifier->name))
|
|
return TK_AT_INTERFACE;
|
|
if (!strcmp("@implementation", tkidentifier->name))
|
|
return TK_AT_IMPLEMENTATION;
|
|
if (!strcmp("@protocol", tkidentifier->name))
|
|
return TK_AT_PROTOCOL;
|
|
if (!strcmp("@end", tkidentifier->name))
|
|
return TK_AT_END;
|
|
if (!strcmp("@private", tkidentifier->name))
|
|
return TK_AT_PRIVATE;
|
|
if (!strcmp("@protected", tkidentifier->name))
|
|
return TK_AT_PROTECTED;
|
|
if (!strcmp("@public", tkidentifier->name))
|
|
return TK_AT_PUBLIC;
|
|
if (!strcmp("@class", tkidentifier->name))
|
|
return TK_AT_CLASS;
|
|
if (!strcmp("@selector", tkidentifier->name))
|
|
return TK_AT_SELECTOR;
|
|
if (!strcmp("@encode", tkidentifier->name))
|
|
return TK_AT_ENCODE;
|
|
if (!strcmp("@defs", tkidentifier->name))
|
|
return TK_AT_DEFS;
|
|
}
|
|
|
|
if (in_assembler)
|
|
return TK_IDENTIFIER;
|
|
|
|
pos = start_pos;
|
|
}
|
|
|
|
return '@';
|
|
}
|
|
|
|
static short tperc(short) {
|
|
char t2;
|
|
at_linestart = 0;
|
|
t2 = prepcurchar();
|
|
if (t2 == '=') {
|
|
pos = nextcharpos;
|
|
return TK_MOD_ASSIGN;
|
|
}
|
|
if (t2 == '>' && copts.cplusplus && !preprocessing_only) {
|
|
pos = nextcharpos;
|
|
return '}';
|
|
}
|
|
return '%';
|
|
}
|
|
|
|
static short texcl(void) {
|
|
at_linestart = 0;
|
|
if (prepcurchar() == '=') {
|
|
pos = nextcharpos;
|
|
return TK_LOGICAL_NE;
|
|
}
|
|
return '!';
|
|
}
|
|
|
|
static short tplus(void) {
|
|
short t2;
|
|
at_linestart = 0;
|
|
t2 = prepcurchar();
|
|
if (t2 == '=') {
|
|
pos = nextcharpos;
|
|
return TK_ADD_ASSIGN;
|
|
}
|
|
if (t2 == '+') {
|
|
pos = nextcharpos;
|
|
return TK_INCREMENT;
|
|
}
|
|
return '+';
|
|
}
|
|
|
|
static short tminu(void) {
|
|
short t2;
|
|
at_linestart = 0;
|
|
t2 = prepcurchar();
|
|
if (t2 == '=') {
|
|
pos = nextcharpos;
|
|
return TK_SUB_ASSIGN;
|
|
}
|
|
if (t2 == '-') {
|
|
pos = nextcharpos;
|
|
return TK_DECREMENT;
|
|
}
|
|
if (t2 == '>') {
|
|
pos = nextcharpos;
|
|
if (copts.cplusplus && prepcurchar() == '*') {
|
|
pos = nextcharpos;
|
|
return TK_ARROW_STAR;
|
|
}
|
|
return TK_ARROW;
|
|
}
|
|
return '-';
|
|
}
|
|
|
|
static short torrr(void) {
|
|
short t2;
|
|
at_linestart = 0;
|
|
t2 = prepcurchar();
|
|
if (t2 == '=') {
|
|
pos = nextcharpos;
|
|
return TK_OR_ASSIGN;
|
|
}
|
|
if (t2 == '|') {
|
|
pos = nextcharpos;
|
|
return TK_LOGICAL_OR;
|
|
}
|
|
return '|';
|
|
}
|
|
|
|
static short tampe(void) {
|
|
short t2;
|
|
at_linestart = 0;
|
|
t2 = prepcurchar();
|
|
if (t2 == '=') {
|
|
pos = nextcharpos;
|
|
return TK_AND_ASSIGN;
|
|
}
|
|
if (t2 == '&') {
|
|
pos = nextcharpos;
|
|
return TK_LOGICAL_AND;
|
|
}
|
|
return '&';
|
|
}
|
|
|
|
static short tpowe(void) {
|
|
at_linestart = 0;
|
|
if (prepcurchar() == '=') {
|
|
pos = nextcharpos;
|
|
return TK_XOR_ASSIGN;
|
|
}
|
|
return '^';
|
|
}
|
|
|
|
static short tdivi(void) {
|
|
at_linestart = 0;
|
|
if (prepcurchar() == '=') {
|
|
pos = nextcharpos;
|
|
return TK_DIV_ASSIGN;
|
|
}
|
|
return '/';
|
|
}
|
|
|
|
// forward decl
|
|
static short tnumb(short t);
|
|
|
|
static short tzero(short t) {
|
|
char *p;
|
|
short ch;
|
|
Boolean failed;
|
|
Boolean floatFailed;
|
|
|
|
if (InlineAsm_gccmode && InlineAsm_labelref)
|
|
return tnumb(t);
|
|
|
|
at_linestart = 0;
|
|
|
|
p = pos - 1;
|
|
ch = prepnextchar();
|
|
if (ch == 'x' || ch == 'X') {
|
|
p = CInt64_ScanHexString(&tkintconst, pos, &failed);
|
|
if (pos == p)
|
|
CError_Error(CErrorStr105);
|
|
pos = p;
|
|
} else if (!copts.ANSIstrict && (ch == 'b' || ch == 'B')) {
|
|
p = CInt64_ScanBinString(&tkintconst, pos, &failed);
|
|
if (pos == p)
|
|
CError_Error(CErrorStr105);
|
|
pos = p;
|
|
} else {
|
|
while (ch >= '0' && ch <= '9')
|
|
ch = prepnextchar();
|
|
|
|
switch (ch) {
|
|
case '.':
|
|
case 'E':
|
|
case 'e':
|
|
pos = CMach_FloatScan(p, &tkfloatconst, &floatFailed);
|
|
if (floatFailed)
|
|
CPrep_Error(CErrorStr154);
|
|
tksize = floatsuffix(prepcurchar());
|
|
return TK_FLOATCONST;
|
|
}
|
|
|
|
pos = CInt64_ScanOctString(&tkintconst, p, &failed);
|
|
}
|
|
|
|
if (failed) {
|
|
CPrep_Error(CErrorStr154);
|
|
tkintconst = cint64_zero;
|
|
}
|
|
|
|
tksize = intsuffix(prepcurchar(), 1);
|
|
return TK_INTCONST;
|
|
}
|
|
|
|
static short tpoin(void) {
|
|
char *p;
|
|
short ch;
|
|
Boolean failed;
|
|
|
|
at_linestart = 0;
|
|
|
|
p = pos - 1;
|
|
ch = prepnextchar();
|
|
|
|
if (ch >= '0' && ch <= '9') {
|
|
pos = CMach_FloatScan(p, &tkfloatconst, &failed);
|
|
if (failed)
|
|
CPrep_Error(CErrorStr154);
|
|
tksize = floatsuffix(prepcurchar());
|
|
return TK_FLOATCONST;
|
|
}
|
|
|
|
if (copts.cplusplus && ch == '*')
|
|
return TK_DOT_STAR;
|
|
|
|
if (ch == '.' && prepnextchar() == '.')
|
|
return TK_ELLIPSIS;
|
|
|
|
pos = p + 1;
|
|
return '.';
|
|
}
|
|
|
|
static short tnumb(short t) {
|
|
char *p;
|
|
short ch;
|
|
Boolean failed;
|
|
Boolean floatFailed;
|
|
|
|
at_linestart = 0;
|
|
|
|
p = pos - 1;
|
|
pos = CInt64_ScanDecString(&tkintconst, p, &failed);
|
|
|
|
ch = prepcurchar();
|
|
if (ch == '.' || ch == 'e' || ch == 'E') {
|
|
pos = CMach_FloatScan(p, &tkfloatconst, &floatFailed);
|
|
if (floatFailed)
|
|
CPrep_Error(CErrorStr154);
|
|
tksize = floatsuffix(prepcurchar());
|
|
return TK_FLOATCONST;
|
|
}
|
|
|
|
if (failed) {
|
|
CPrep_Error(CErrorStr154);
|
|
tkintconst = cint64_zero;
|
|
}
|
|
|
|
tksize = intsuffix(prepcurchar(), 0);
|
|
return TK_INTCONST;
|
|
}
|
|
|
|
static short tiden(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
else
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrL(void) {
|
|
short ch;
|
|
|
|
at_linestart = 0;
|
|
|
|
if ((ch = prepcurchar()) == '\'') {
|
|
widestring = 1;
|
|
pos = nextcharpos;
|
|
ch = tapos(ch);
|
|
widestring = 0;
|
|
|
|
tksize = (copts.wchar_type && copts.cplusplus) ? IT_WCHAR_T : IT_INT;
|
|
return ch;
|
|
}
|
|
|
|
if (ch == '"') {
|
|
widestring = 1;
|
|
pos = nextcharpos;
|
|
ch = tquot(ch);
|
|
widestring = 0;
|
|
return ch;
|
|
}
|
|
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchra(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("auto", tkidentifier->name))
|
|
return TK_AUTO;
|
|
if ((copts.cplusplus || !copts.onlystdkeywords) && !strcmp("asm", tkidentifier->name))
|
|
return TK_ASM;
|
|
if (copts.cplusplus && !in_assembler && !preprocessing_only) {
|
|
if (!strcmp("and", tkidentifier->name))
|
|
return TK_LOGICAL_AND;
|
|
if (!strcmp("and_eq", tkidentifier->name))
|
|
return TK_AND_ASSIGN;
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrb(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("break", tkidentifier->name))
|
|
return TK_BREAK;
|
|
if (copts.cplusplus) {
|
|
if (copts.booltruefalse && !strcmp("bool", tkidentifier->name))
|
|
return TK_BOOL;
|
|
if (!in_assembler && !preprocessing_only) {
|
|
if (!strcmp("bitand", tkidentifier->name))
|
|
return '&';
|
|
if (!strcmp("bitor", tkidentifier->name))
|
|
return '|';
|
|
}
|
|
}
|
|
if (copts.objective_c) {
|
|
if (!strcmp("bycopy", tkidentifier->name))
|
|
return TK_BYCOPY;
|
|
if (!strcmp("byref", tkidentifier->name))
|
|
return TK_BYREF;
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrc(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("case", tkidentifier->name))
|
|
return TK_CASE;
|
|
if (!strcmp("char", tkidentifier->name))
|
|
return TK_CHAR;
|
|
if (!strcmp("const", tkidentifier->name))
|
|
return TK_CONST;
|
|
if (!strcmp("continue", tkidentifier->name))
|
|
return TK_CONTINUE;
|
|
if (copts.cplusplus) {
|
|
if (!strcmp("const_cast", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_CONST_CAST;
|
|
}
|
|
if (!strcmp("catch", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_CATCH;
|
|
}
|
|
if (!strcmp("class", tkidentifier->name))
|
|
return TK_CLASS;
|
|
if (!in_assembler && !preprocessing_only) {
|
|
if (!strcmp("compl", tkidentifier->name))
|
|
return '~';
|
|
}
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrd(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("default", tkidentifier->name))
|
|
return TK_DEFAULT;
|
|
if (!strcmp("do", tkidentifier->name))
|
|
return TK_DO;
|
|
if (!strcmp("double", tkidentifier->name))
|
|
return TK_DOUBLE;
|
|
if (copts.cplusplus) {
|
|
if (!strcmp("delete", tkidentifier->name))
|
|
return TK_DELETE;
|
|
if (!strcmp("dynamic_cast", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_DYNAMIC_CAST;
|
|
}
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchre(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("else", tkidentifier->name))
|
|
return TK_ELSE;
|
|
if (!strcmp("enum", tkidentifier->name))
|
|
return TK_ENUM;
|
|
if (!strcmp("extern", tkidentifier->name))
|
|
return TK_EXTERN;
|
|
if (copts.cplusplus) {
|
|
if (!strcmp("explicit", tkidentifier->name))
|
|
return TK_EXPLICIT;
|
|
if (!strcmp("export", tkidentifier->name) && !copts.ecplusplus)
|
|
return TK_EXPORT;
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrf(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("float", tkidentifier->name))
|
|
return TK_FLOAT;
|
|
if (!strcmp("for", tkidentifier->name))
|
|
return TK_FOR;
|
|
if (copts.cplusplus) {
|
|
if (!strcmp("friend", tkidentifier->name))
|
|
return TK_FRIEND;
|
|
if (copts.booltruefalse && !strcmp("false", tkidentifier->name))
|
|
return TK_FALSE;
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrg(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("goto", tkidentifier->name))
|
|
return TK_GOTO;
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchri(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("if", tkidentifier->name))
|
|
return TK_IF;
|
|
if (!strcmp("int", tkidentifier->name))
|
|
return TK_INT;
|
|
if (copts.cplusplus || copts.c9x) {
|
|
if (!strcmp("inline", tkidentifier->name))
|
|
return TK_INLINE;
|
|
} else if (!copts.onlystdkeywords) {
|
|
if (!strcmp("inline", tkidentifier->name))
|
|
return TK_INLINE;
|
|
}
|
|
if (copts.objective_c) {
|
|
if (!strcmp("in", tkidentifier->name))
|
|
return TK_IN;
|
|
if (!strcmp("inout", tkidentifier->name))
|
|
return TK_INOUT;
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrl(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("long", tkidentifier->name))
|
|
return TK_LONG;
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrm(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (copts.cplusplus && !strcmp("mutable", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_MUTABLE;
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrn(short t) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (copts.cplusplus && t == 'n') {
|
|
if (!strcmp("new", tkidentifier->name))
|
|
return TK_NEW;
|
|
if (!strcmp("namespace", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_NAMESPACE;
|
|
}
|
|
if (!in_assembler && !preprocessing_only) {
|
|
if (!strcmp("not", tkidentifier->name))
|
|
return '!';
|
|
if (!strcmp("not_eq", tkidentifier->name))
|
|
return TK_LOGICAL_NE;
|
|
}
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchro(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (copts.cplusplus) {
|
|
if (!strcmp("operator", tkidentifier->name))
|
|
return TK_OPERATOR;
|
|
if (!in_assembler && !preprocessing_only) {
|
|
if (!strcmp("or", tkidentifier->name))
|
|
return TK_LOGICAL_OR;
|
|
if (!strcmp("or_eq", tkidentifier->name))
|
|
return TK_OR_ASSIGN;
|
|
}
|
|
}
|
|
if (copts.objective_c) {
|
|
if (!strcmp("out", tkidentifier->name))
|
|
return TK_OUT;
|
|
if (!strcmp("oneway", tkidentifier->name))
|
|
return TK_ONEWAY;
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrp(short t) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!copts.onlystdkeywords && !strcmp("pascal", tkidentifier->name))
|
|
return TK_PASCAL;
|
|
if (copts.cplusplus && t == 'p') {
|
|
if (!strcmp("private", tkidentifier->name))
|
|
return TK_PRIVATE;
|
|
if (!strcmp("protected", tkidentifier->name))
|
|
return TK_PROTECTED;
|
|
if (!strcmp("public", tkidentifier->name))
|
|
return TK_PUBLIC;
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrr(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("register", tkidentifier->name))
|
|
return TK_REGISTER;
|
|
if (!strcmp("return", tkidentifier->name))
|
|
return TK_RETURN;
|
|
if (copts.cplusplus && !strcmp("reinterpret_cast", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_REINTERPRET_CAST;
|
|
}
|
|
if (copts.c9x && !strcmp("restrict", tkidentifier->name))
|
|
return TK_RESTRICT;
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrs(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("short", tkidentifier->name))
|
|
return TK_SHORT;
|
|
if (!strcmp("signed", tkidentifier->name))
|
|
return TK_SIGNED;
|
|
if (!strcmp("sizeof", tkidentifier->name))
|
|
return TK_SIZEOF;
|
|
if (!strcmp("static", tkidentifier->name))
|
|
return TK_STATIC;
|
|
if (!strcmp("struct", tkidentifier->name))
|
|
return TK_STRUCT;
|
|
if (!strcmp("switch", tkidentifier->name))
|
|
return TK_SWITCH;
|
|
if (copts.cplusplus && !strcmp("static_cast", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_STATIC_CAST;
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrt(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("typedef", tkidentifier->name))
|
|
return TK_TYPEDEF;
|
|
if (copts.gcc_extensions && !strcmp("typeof", tkidentifier->name))
|
|
return TK_UU_TYPEOF_UU;
|
|
if (copts.cplusplus) {
|
|
if (!strcmp("this", tkidentifier->name))
|
|
return TK_THIS;
|
|
if (copts.booltruefalse && !strcmp("true", tkidentifier->name))
|
|
return TK_TRUE;
|
|
if (!strcmp("template", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_TEMPLATE;
|
|
}
|
|
if (!strcmp("try", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_TRY;
|
|
}
|
|
if (!strcmp("throw", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_THROW;
|
|
}
|
|
if (!strcmp("typeid", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_TYPEID;
|
|
}
|
|
if (!strcmp("typename", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_TYPENAME;
|
|
}
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchru(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("union", tkidentifier->name))
|
|
return TK_UNION;
|
|
if (!strcmp("unsigned", tkidentifier->name))
|
|
return TK_UNSIGNED;
|
|
if (copts.cplusplus && !strcmp("using", tkidentifier->name)) {
|
|
if (copts.ecplusplus)
|
|
CPrep_Warning(CErrorStr339);
|
|
return TK_USING;
|
|
}
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrv(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("void", tkidentifier->name))
|
|
return TK_VOID;
|
|
if (!strcmp("volatile", tkidentifier->name))
|
|
return TK_VOLATILE;
|
|
if (copts.cplusplus && !strcmp("virtual", tkidentifier->name))
|
|
return TK_VIRTUAL;
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrw(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
if (!strcmp("while", tkidentifier->name))
|
|
return TK_WHILE;
|
|
if (copts.cplusplus && copts.wchar_type && !strcmp("wchar_t", tkidentifier->name))
|
|
return TK_WCHAR_T;
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchrx(short t) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
|
|
if (copts.cplusplus && t == 'x' && !in_assembler && !preprocessing_only) {
|
|
if (!strcmp("xor", tkidentifier->name))
|
|
return '^';
|
|
if (!strcmp("xor_eq", tkidentifier->name))
|
|
return TK_XOR_ASSIGN;
|
|
}
|
|
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short tchr_(void) {
|
|
at_linestart = 0;
|
|
pos = ReadIdentifier(pos - 1);
|
|
if (macrocheck && macrotest())
|
|
return 0;
|
|
|
|
if (!strcmp("__stdcall", tkidentifier->name))
|
|
return TK_UU_STDCALL;
|
|
if (!strcmp("__cdecl", tkidentifier->name))
|
|
return TK_UU_CDECL;
|
|
if (!strcmp("__fastcall", tkidentifier->name))
|
|
return TK_UU_FASTCALL;
|
|
if (!strcmp("__declspec", tkidentifier->name))
|
|
return TK_UU_DECLSPEC;
|
|
if (!strcmp("__asm", tkidentifier->name))
|
|
return TK_ASM;
|
|
if (!strcmp("__asm__", tkidentifier->name))
|
|
return TK_ASM;
|
|
if (!strcmp("__inline", tkidentifier->name))
|
|
return TK_INLINE;
|
|
if (!strcmp("__inline__", tkidentifier->name))
|
|
return TK_INLINE;
|
|
if (!strcmp("__restrict", tkidentifier->name))
|
|
return TK_RESTRICT;
|
|
if (!strcmp("__restrict__", tkidentifier->name))
|
|
return TK_RESTRICT;
|
|
if (!strcmp("__attribute__", tkidentifier->name))
|
|
return TK_UU_ATTRIBUTE_UU;
|
|
if (!strcmp("__far", tkidentifier->name))
|
|
return TK_UU_FAR;
|
|
if (!strcmp("__alignof__", tkidentifier->name))
|
|
return TK_UU_ALIGNOF_UU;
|
|
if (!strcmp("__typeof__", tkidentifier->name))
|
|
return TK_UU_TYPEOF_UU;
|
|
if (copts.c9x) {
|
|
if (!strcmp("_Bool", tkidentifier->name))
|
|
return TK_BOOL;
|
|
if (!strcmp("_Complex", tkidentifier->name))
|
|
return TK_U_COMPLEX;
|
|
if (!strcmp("_Imaginary", tkidentifier->name))
|
|
return TK_U_IMAGINARY;
|
|
}
|
|
if (copts.altivec_model && !strcmp("__vector", tkidentifier->name))
|
|
return TK_UU_VECTOR;
|
|
return TK_IDENTIFIER;
|
|
}
|
|
|
|
static short token(short t) {
|
|
at_linestart = 0;
|
|
return t;
|
|
}
|
|
|
|
static short tdoll(short t) {
|
|
at_linestart = 0;
|
|
return t;
|
|
}
|
|
|
|
static short tisid(void) {
|
|
if (!tokenstacklevel)
|
|
CError_Error(CErrorStr105);
|
|
return 0;
|
|
}
|
|
|
|
static short tnull(short t) {
|
|
if (tokenstacklevel > 0 || pos >= prep_file_end) {
|
|
at_linestart = 0;
|
|
return t;
|
|
} else {
|
|
pos[-1] = -64;
|
|
return TK_ILLEGAL;
|
|
}
|
|
}
|
|
|
|
static short t0x1a(void) {
|
|
if (*pos == 0)
|
|
return 0;
|
|
else
|
|
return TK_ILLEGAL;
|
|
}
|
|
|
|
typedef short (*TokenizePtr)(short);
|
|
#define F(func) ((TokenizePtr) (&func))
|
|
|
|
static TokenizePtr cprep_tokenize[256] = {
|
|
F(tnull), F(tille), F(tille), F(tille), F(tisid), F(tisid), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tcret), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(t0x1a), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(texcl), F(tquot), F(thash), F(tdoll), F(tperc), F(tampe), F(tapos),
|
|
F(token), F(token), F(tmult), F(tplus), F(token), F(tminu), F(tpoin), F(tdivi),
|
|
F(tzero), F(tnumb), F(tnumb), F(tnumb), F(tnumb), F(tnumb), F(tnumb), F(tnumb),
|
|
F(tnumb), F(tnumb), F(tcolo), F(token), F(tless), F(tequa), F(tgrea), F(token),
|
|
F(tatsg), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden),
|
|
F(tiden), F(tiden), F(tiden), F(tiden), F(tchrL), F(tiden), F(tchrn), F(tiden),
|
|
F(tchrp), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden), F(tiden),
|
|
F(tchrx), F(tiden), F(tiden), F(token), F(token), F(token), F(tpowe), F(tchr_),
|
|
F(token), F(tchra), F(tchrb), F(tchrc), F(tchrd), F(tchre), F(tchrf), F(tchrg),
|
|
F(tiden), F(tchri), F(tiden), F(tiden), F(tchrl), F(tchrm), F(tchrn), F(tchro),
|
|
F(tchrp), F(tiden), F(tchrr), F(tchrs), F(tchrt), F(tchru), F(tchrv), F(tchrw),
|
|
F(tchrx), F(tiden), F(tiden), F(token), F(torrr), F(token), F(token), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille),
|
|
F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille), F(tille)
|
|
};
|
|
|
|
short lookahead(void) {
|
|
SInt32 state;
|
|
short t;
|
|
|
|
CPrep_TokenStreamGetState(&state);
|
|
t = lex();
|
|
CPrep_TokenStreamSetState(&state);
|
|
|
|
return t;
|
|
}
|
|
|
|
short lookahead_noeol(void) {
|
|
SInt32 state;
|
|
short t;
|
|
|
|
CPrep_TokenStreamGetState(&state);
|
|
do {
|
|
t = lex();
|
|
} while (t == TK_EOL);
|
|
CPrep_TokenStreamSetState(&state);
|
|
|
|
return t;
|
|
}
|
|
|
|
typedef struct StringChunk {
|
|
struct StringChunk *next;
|
|
char *data;
|
|
SInt32 offset;
|
|
SInt32 size;
|
|
} StringChunk;
|
|
|
|
static void CPrep_StringConCat(Boolean flag) {
|
|
StringPtr buffer;
|
|
StringChunk *chunks;
|
|
StringChunk *chunk;
|
|
char *saveString;
|
|
SInt32 saveSize;
|
|
SInt32 offset;
|
|
Boolean savePascalString;
|
|
TStreamElement *elem;
|
|
short ch;
|
|
|
|
saveString = tkstring;
|
|
saveSize = tksize;
|
|
savePascalString = ispascalstring;
|
|
|
|
cprep_strconcat = 1;
|
|
|
|
chunks = NULL;
|
|
offset = tksize;
|
|
|
|
while (1) {
|
|
ch = lookahead_noeol();
|
|
if (ch != TK_STRING && ch != TK_STRING_WIDE) {
|
|
ispascalstring = savePascalString;
|
|
if (chunks) {
|
|
tksize = offset;
|
|
buffer = galloc(offset);
|
|
tkstring = (char *) buffer;
|
|
|
|
memcpy(buffer, saveString, saveSize);
|
|
for (chunk = chunks; chunk; chunk = chunk->next)
|
|
memcpy(buffer + chunk->offset, chunk->data, chunk->size);
|
|
|
|
if (savePascalString) {
|
|
if (offset > 256) {
|
|
CError_Error(CErrorStr106);
|
|
offset = 256;
|
|
}
|
|
buffer[0] = offset - 1;
|
|
} else if (flag) {
|
|
CMach_InitIntMem(TYPE(&stwchar), cint64_zero, buffer + offset - stwchar.size);
|
|
} else {
|
|
CMach_InitIntMem(TYPE(&stchar), cint64_zero, buffer + offset - stchar.size);
|
|
}
|
|
|
|
elem = ts_current - 1;
|
|
elem->data.tkstring.data = (char *) buffer;
|
|
elem->data.tkstring.size = offset;
|
|
elem->subtype = ispascalstring;
|
|
cprep_strconcat = 0;
|
|
} else {
|
|
tkstring = saveString;
|
|
tksize = saveSize;
|
|
cprep_strconcat = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
do {
|
|
ch = lex();
|
|
elem = --ts_current;
|
|
memmove(elem, elem + 1, sizeof(TStreamElement) * ts_preread_elements);
|
|
} while (ch == TK_EOL);
|
|
|
|
chunk = lalloc(sizeof(StringChunk));
|
|
chunk->next = chunks;
|
|
chunk->data = tkstring;
|
|
chunk->size = tksize - 1;
|
|
chunk->offset = offset - 1;
|
|
chunks = chunk;
|
|
|
|
if (ispascalstring)
|
|
chunk->data++;
|
|
if (savePascalString)
|
|
chunk->offset++;
|
|
|
|
if (ch == TK_STRING_WIDE)
|
|
chunk->size = chunk->size + 1 - stwchar.size;
|
|
if (flag)
|
|
chunk->offset = chunk->offset + 1 - stwchar.size;
|
|
|
|
offset += chunk->size;
|
|
}
|
|
}
|
|
|
|
short lex(void) {
|
|
short t;
|
|
|
|
while (1) {
|
|
if (ts_preread_elements <= 0)
|
|
break;
|
|
|
|
t = ts_current->tokentype;
|
|
if (t < 0) {
|
|
switch (t) {
|
|
case TK_INTCONST:
|
|
tkintconst = ts_current->data.tkintconst;
|
|
tksize = ts_current->subtype;
|
|
break;
|
|
case TK_FLOATCONST:
|
|
tkfloatconst = ts_current->data.tkfloatconst;
|
|
tksize = ts_current->subtype;
|
|
break;
|
|
case TK_IDENTIFIER:
|
|
tkidentifier = ts_current->data.tkidentifier;
|
|
break;
|
|
case TK_STRING:
|
|
case TK_STRING_WIDE:
|
|
tkstring = ts_current->data.tkstring.data;
|
|
tksize = ts_current->data.tkstring.size;
|
|
ispascalstring = ts_current->subtype;
|
|
break;
|
|
case TK_EOL:
|
|
nlflag = 1;
|
|
if (!cprep_eoltokens) {
|
|
ts_current++;
|
|
ts_preread_elements--;
|
|
continue;
|
|
}
|
|
break;
|
|
default:
|
|
CError_FATAL(3007);
|
|
}
|
|
}
|
|
|
|
ts_current++;
|
|
ts_preread_elements--;
|
|
return t;
|
|
}
|
|
|
|
while (1) {
|
|
t = prepskipnextchar();
|
|
|
|
ts_current->tokenfile = prep_file;
|
|
if (tokenstacklevel > 0) {
|
|
ts_current->tokenoffset = tokenstack[0].pos - prep_file_start;
|
|
macropos = pos;
|
|
} else {
|
|
ts_current->tokenoffset = pos - prep_file_start;
|
|
}
|
|
ts_current->tokenline = linenumber;
|
|
pos = nextcharpos;
|
|
|
|
t = cprep_tokenize[t](t);
|
|
if (t != 0) {
|
|
if (ts_current >= ts_last)
|
|
CPrep_TSBufferGrow(1024);
|
|
ts_current->tokentype = t;
|
|
|
|
if ((t = ts_current->tokentype) < 0) {
|
|
switch (t) {
|
|
case TK_INTCONST:
|
|
ts_current->data.tkintconst = tkintconst;
|
|
ts_current->subtype = tksize;
|
|
break;
|
|
case TK_FLOATCONST:
|
|
ts_current->data.tkfloatconst = tkfloatconst;
|
|
ts_current->subtype = tksize;
|
|
break;
|
|
case TK_IDENTIFIER:
|
|
ts_current->data.tkidentifier = tkidentifier;
|
|
break;
|
|
case TK_STRING:
|
|
case TK_STRING_WIDE:
|
|
ts_current->data.tkstring.data = tkstring;
|
|
ts_current->data.tkstring.size = tksize;
|
|
ts_current->subtype = ispascalstring;
|
|
if (!cprep_strconcat) {
|
|
ts_current++;
|
|
CPrep_StringConCat(t == TK_STRING_WIDE);
|
|
return t;
|
|
}
|
|
break;
|
|
case TK_ILLEGAL:
|
|
ts_current++;
|
|
CError_Error(CErrorStr105);
|
|
ts_current--;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ts_current++;
|
|
return t;
|
|
}
|
|
|
|
if (*pos == 0) {
|
|
if (tokenstacklevel > 0) {
|
|
poptokenseq();
|
|
} else if (tokenstacklevel > 0 || pos >= prep_file_end) {
|
|
if (filesp > 0)
|
|
popfile();
|
|
else
|
|
return 0;
|
|
} else {
|
|
ts_current++;
|
|
CError_ErrorTerm(CErrorStr105);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
short plex(void) {
|
|
short t;
|
|
|
|
while (1) {
|
|
t = prepskipnextchar();
|
|
pos = nextcharpos;
|
|
if ((t = cprep_tokenize[t](t)))
|
|
return t;
|
|
|
|
if (!*pos) {
|
|
if (tokenstacklevel > 0) {
|
|
poptokenseq();
|
|
} else if (filesp > 0) {
|
|
popfile();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
short lexidentifier(void) {
|
|
short t;
|
|
char *save_pos;
|
|
|
|
t = prepskipnextchar();
|
|
pos = nextcharpos;
|
|
at_linestart = 0;
|
|
if ((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z') || (t == '_')) {
|
|
pos = ReadIdentifier(pos - 1);
|
|
return TK_IDENTIFIER;
|
|
} else if (t == '.') {
|
|
save_pos = pos;
|
|
if (prepnextchar() == '.' && prepnextchar() == '.')
|
|
return TK_ELLIPSIS;
|
|
else
|
|
pos = save_pos;
|
|
}
|
|
return t;
|
|
}
|