mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
use self hosted translate-c for cimports
This commit is contained in:
parent
bda355d976
commit
fceda07f94
@ -448,7 +448,6 @@ set(ZIG_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/src/bigfloat.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/bigint.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/buffer.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/cache_hash.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/codegen.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/compiler.cpp"
|
||||
@ -465,7 +464,6 @@ set(ZIG_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/src/range_set.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/target.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/translate_c.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/util.cpp"
|
||||
"${ZIG_SOURCES_MEM_PROFILE}"
|
||||
)
|
||||
|
||||
@ -1,840 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Andrew Kelley
|
||||
*
|
||||
* This file is part of zig, which is MIT licensed.
|
||||
* See http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "c_tokenizer.hpp"
|
||||
#include <inttypes.h>
|
||||
|
||||
#define WHITESPACE_EXCEPT_N \
|
||||
' ': \
|
||||
case '\t': \
|
||||
case '\v': \
|
||||
case '\f'
|
||||
|
||||
#define DIGIT_NON_ZERO \
|
||||
'1': \
|
||||
case '2': \
|
||||
case '3': \
|
||||
case '4': \
|
||||
case '5': \
|
||||
case '6': \
|
||||
case '7': \
|
||||
case '8': \
|
||||
case '9'
|
||||
|
||||
#define DIGIT \
|
||||
'0': \
|
||||
case DIGIT_NON_ZERO
|
||||
|
||||
#define ALPHA \
|
||||
'a': \
|
||||
case 'b': \
|
||||
case 'c': \
|
||||
case 'd': \
|
||||
case 'e': \
|
||||
case 'f': \
|
||||
case 'g': \
|
||||
case 'h': \
|
||||
case 'i': \
|
||||
case 'j': \
|
||||
case 'k': \
|
||||
case 'l': \
|
||||
case 'm': \
|
||||
case 'n': \
|
||||
case 'o': \
|
||||
case 'p': \
|
||||
case 'q': \
|
||||
case 'r': \
|
||||
case 's': \
|
||||
case 't': \
|
||||
case 'u': \
|
||||
case 'v': \
|
||||
case 'w': \
|
||||
case 'x': \
|
||||
case 'y': \
|
||||
case 'z': \
|
||||
case 'A': \
|
||||
case 'B': \
|
||||
case 'C': \
|
||||
case 'D': \
|
||||
case 'E': \
|
||||
case 'F': \
|
||||
case 'G': \
|
||||
case 'H': \
|
||||
case 'I': \
|
||||
case 'J': \
|
||||
case 'K': \
|
||||
case 'L': \
|
||||
case 'M': \
|
||||
case 'N': \
|
||||
case 'O': \
|
||||
case 'P': \
|
||||
case 'Q': \
|
||||
case 'R': \
|
||||
case 'S': \
|
||||
case 'T': \
|
||||
case 'U': \
|
||||
case 'V': \
|
||||
case 'W': \
|
||||
case 'X': \
|
||||
case 'Y': \
|
||||
case 'Z'
|
||||
|
||||
#define IDENT_START \
|
||||
ALPHA: \
|
||||
case '_'
|
||||
|
||||
#define IDENT \
|
||||
IDENT_START: \
|
||||
case DIGIT
|
||||
|
||||
#define LINE_ENDING \
|
||||
'\r': \
|
||||
case '\n'
|
||||
|
||||
static void begin_token(CTokenize *ctok, CTokId id) {
|
||||
assert(ctok->cur_tok == nullptr);
|
||||
ctok->tokens.add_one();
|
||||
ctok->cur_tok = &ctok->tokens.last();
|
||||
ctok->cur_tok->id = id;
|
||||
|
||||
switch (id) {
|
||||
case CTokIdStrLit:
|
||||
memset(&ctok->cur_tok->data.str_lit, 0, sizeof(Buf));
|
||||
buf_resize(&ctok->cur_tok->data.str_lit, 0);
|
||||
break;
|
||||
case CTokIdSymbol:
|
||||
memset(&ctok->cur_tok->data.symbol, 0, sizeof(Buf));
|
||||
buf_resize(&ctok->cur_tok->data.symbol, 0);
|
||||
break;
|
||||
case CTokIdNumLitInt:
|
||||
ctok->cur_tok->data.num_lit_int.x = 0;
|
||||
ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixNone;
|
||||
break;
|
||||
case CTokIdCharLit:
|
||||
case CTokIdNumLitFloat:
|
||||
case CTokIdMinus:
|
||||
case CTokIdLParen:
|
||||
case CTokIdRParen:
|
||||
case CTokIdEOF:
|
||||
case CTokIdDot:
|
||||
case CTokIdAsterisk:
|
||||
case CTokIdBang:
|
||||
case CTokIdTilde:
|
||||
case CTokIdShl:
|
||||
case CTokIdLt:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void end_token(CTokenize *ctok) {
|
||||
ctok->cur_tok = nullptr;
|
||||
}
|
||||
|
||||
static void mark_error(CTokenize *ctok) {
|
||||
ctok->error = true;
|
||||
}
|
||||
|
||||
static void add_char(CTokenize *ctok, uint8_t c) {
|
||||
assert(ctok->cur_tok);
|
||||
if (ctok->cur_tok->id == CTokIdCharLit) {
|
||||
ctok->cur_tok->data.char_lit = c;
|
||||
ctok->state = CTokStateExpectEndQuot;
|
||||
} else if (ctok->cur_tok->id == CTokIdStrLit) {
|
||||
buf_append_char(&ctok->cur_tok->data.str_lit, c);
|
||||
ctok->state = CTokStateString;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
static void hex_digit(CTokenize *ctok, uint8_t value) {
|
||||
// TODO @mul_with_overflow
|
||||
ctok->cur_tok->data.num_lit_int.x *= 16;
|
||||
// TODO @add_with_overflow
|
||||
ctok->cur_tok->data.num_lit_int.x += value;
|
||||
|
||||
static const uint8_t hex_digit[] = "0123456789abcdef";
|
||||
buf_append_char(&ctok->buf, hex_digit[value]);
|
||||
}
|
||||
|
||||
static void end_float(CTokenize *ctok) {
|
||||
// TODO detect errors, overflow, and underflow
|
||||
double value = strtod(buf_ptr(&ctok->buf), nullptr);
|
||||
|
||||
ctok->cur_tok->data.num_lit_float = value;
|
||||
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
|
||||
}
|
||||
|
||||
void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
|
||||
ctok->tokens.resize(0);
|
||||
ctok->state = CTokStateStart;
|
||||
ctok->error = false;
|
||||
ctok->cur_tok = nullptr;
|
||||
|
||||
buf_resize(&ctok->buf, 0);
|
||||
|
||||
for (; *c; c += 1) {
|
||||
switch (ctok->state) {
|
||||
case CTokStateStart:
|
||||
switch (*c) {
|
||||
case WHITESPACE_EXCEPT_N:
|
||||
break;
|
||||
case '\'':
|
||||
ctok->state = CTokStateExpectChar;
|
||||
begin_token(ctok, CTokIdCharLit);
|
||||
break;
|
||||
case '\"':
|
||||
ctok->state = CTokStateString;
|
||||
begin_token(ctok, CTokIdStrLit);
|
||||
break;
|
||||
case '/':
|
||||
ctok->state = CTokStateOpenComment;
|
||||
break;
|
||||
case '\\':
|
||||
ctok->state = CTokStateBackslash;
|
||||
break;
|
||||
case LINE_ENDING:
|
||||
goto found_end_of_macro;
|
||||
case IDENT_START:
|
||||
ctok->state = CTokStateIdentifier;
|
||||
begin_token(ctok, CTokIdSymbol);
|
||||
buf_append_char(&ctok->cur_tok->data.symbol, *c);
|
||||
break;
|
||||
case DIGIT_NON_ZERO:
|
||||
ctok->state = CTokStateDecimal;
|
||||
begin_token(ctok, CTokIdNumLitInt);
|
||||
ctok->cur_tok->data.num_lit_int.x = *c - '0';
|
||||
buf_resize(&ctok->buf, 0);
|
||||
buf_append_char(&ctok->buf, *c);
|
||||
break;
|
||||
case '0':
|
||||
ctok->state = CTokStateGotZero;
|
||||
begin_token(ctok, CTokIdNumLitInt);
|
||||
ctok->cur_tok->data.num_lit_int.x = 0;
|
||||
buf_resize(&ctok->buf, 0);
|
||||
buf_append_char(&ctok->buf, '0');
|
||||
break;
|
||||
case '.':
|
||||
begin_token(ctok, CTokIdDot);
|
||||
end_token(ctok);
|
||||
break;
|
||||
case '<':
|
||||
begin_token(ctok, CTokIdLt);
|
||||
ctok->state = CTokStateGotLt;
|
||||
break;
|
||||
case '(':
|
||||
begin_token(ctok, CTokIdLParen);
|
||||
end_token(ctok);
|
||||
break;
|
||||
case ')':
|
||||
begin_token(ctok, CTokIdRParen);
|
||||
end_token(ctok);
|
||||
break;
|
||||
case '*':
|
||||
begin_token(ctok, CTokIdAsterisk);
|
||||
end_token(ctok);
|
||||
break;
|
||||
case '-':
|
||||
begin_token(ctok, CTokIdMinus);
|
||||
end_token(ctok);
|
||||
break;
|
||||
case '!':
|
||||
begin_token(ctok, CTokIdBang);
|
||||
end_token(ctok);
|
||||
break;
|
||||
case '~':
|
||||
begin_token(ctok, CTokIdTilde);
|
||||
end_token(ctok);
|
||||
break;
|
||||
default:
|
||||
return mark_error(ctok);
|
||||
}
|
||||
break;
|
||||
case CTokStateGotLt:
|
||||
switch (*c) {
|
||||
case '<':
|
||||
ctok->cur_tok->id = CTokIdShl;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
break;
|
||||
default:
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateFloat:
|
||||
switch (*c) {
|
||||
case '.':
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
buf_append_char(&ctok->buf, 'e');
|
||||
ctok->state = CTokStateExpSign;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'l':
|
||||
case 'L':
|
||||
end_float(ctok);
|
||||
break;
|
||||
case DIGIT:
|
||||
buf_append_char(&ctok->buf, *c);
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
end_float(ctok);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateExpSign:
|
||||
switch (*c) {
|
||||
case '+':
|
||||
case '-':
|
||||
ctok->state = CTokStateFloatExpFirst;
|
||||
buf_append_char(&ctok->buf, *c);
|
||||
break;
|
||||
case DIGIT:
|
||||
ctok->state = CTokStateFloatExp;
|
||||
buf_append_char(&ctok->buf, *c);
|
||||
break;
|
||||
default:
|
||||
return mark_error(ctok);
|
||||
}
|
||||
break;
|
||||
case CTokStateFloatExpFirst:
|
||||
switch (*c) {
|
||||
case DIGIT:
|
||||
buf_append_char(&ctok->buf, *c);
|
||||
ctok->state = CTokStateFloatExp;
|
||||
break;
|
||||
default:
|
||||
return mark_error(ctok);
|
||||
}
|
||||
break;
|
||||
case CTokStateFloatExp:
|
||||
switch (*c) {
|
||||
case DIGIT:
|
||||
buf_append_char(&ctok->buf, *c);
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'l':
|
||||
case 'L':
|
||||
end_float(ctok);
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
end_float(ctok);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateDecimal:
|
||||
switch (*c) {
|
||||
case DIGIT:
|
||||
buf_append_char(&ctok->buf, *c);
|
||||
|
||||
// TODO @mul_with_overflow
|
||||
ctok->cur_tok->data.num_lit_int.x *= 10;
|
||||
// TODO @add_with_overflow
|
||||
ctok->cur_tok->data.num_lit_int.x += *c - '0';
|
||||
break;
|
||||
case '\'':
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
ctok->state = CTokStateNumLitIntSuffixU;
|
||||
ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixU;
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
ctok->state = CTokStateNumLitIntSuffixL;
|
||||
ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixL;
|
||||
break;
|
||||
case '.':
|
||||
buf_append_char(&ctok->buf, '.');
|
||||
ctok->cur_tok->id = CTokIdNumLitFloat;
|
||||
ctok->state = CTokStateFloat;
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateGotZero:
|
||||
switch (*c) {
|
||||
case 'x':
|
||||
case 'X':
|
||||
ctok->state = CTokStateHex;
|
||||
break;
|
||||
case '.':
|
||||
ctok->state = CTokStateFloat;
|
||||
ctok->cur_tok->id = CTokIdNumLitFloat;
|
||||
buf_append_char(&ctok->buf, '.');
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
case 'u':
|
||||
case 'U':
|
||||
c -= 1;
|
||||
ctok->state = CTokStateDecimal;
|
||||
continue;
|
||||
default:
|
||||
c -= 1;
|
||||
ctok->state = CTokStateOctal;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateOctal:
|
||||
switch (*c) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
// TODO @mul_with_overflow
|
||||
ctok->cur_tok->data.num_lit_int.x *= 8;
|
||||
// TODO @add_with_overflow
|
||||
ctok->cur_tok->data.num_lit_int.x += *c - '0';
|
||||
break;
|
||||
case '8':
|
||||
case '9':
|
||||
return mark_error(ctok);
|
||||
case '\'':
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateHex:
|
||||
switch (*c) {
|
||||
case '0':
|
||||
hex_digit(ctok, 0);
|
||||
break;
|
||||
case '1':
|
||||
hex_digit(ctok, 1);
|
||||
break;
|
||||
case '2':
|
||||
hex_digit(ctok, 2);
|
||||
break;
|
||||
case '3':
|
||||
hex_digit(ctok, 3);
|
||||
break;
|
||||
case '4':
|
||||
hex_digit(ctok, 4);
|
||||
break;
|
||||
case '5':
|
||||
hex_digit(ctok, 5);
|
||||
break;
|
||||
case '6':
|
||||
hex_digit(ctok, 6);
|
||||
break;
|
||||
case '7':
|
||||
hex_digit(ctok, 7);
|
||||
break;
|
||||
case '8':
|
||||
hex_digit(ctok, 8);
|
||||
break;
|
||||
case '9':
|
||||
hex_digit(ctok, 9);
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
hex_digit(ctok, 10);
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
hex_digit(ctok, 11);
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
hex_digit(ctok, 12);
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
hex_digit(ctok, 13);
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
hex_digit(ctok, 14);
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
hex_digit(ctok, 15);
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
ctok->cur_tok->id = CTokIdNumLitFloat;
|
||||
ctok->state = CTokStateExpSign;
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
// marks the number literal as unsigned
|
||||
ctok->state = CTokStateNumLitIntSuffixU;
|
||||
ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixU;
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
// marks the number literal as long
|
||||
ctok->state = CTokStateNumLitIntSuffixL;
|
||||
ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixL;
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateNumLitIntSuffixU:
|
||||
switch (*c) {
|
||||
case 'l':
|
||||
case 'L':
|
||||
ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLU;
|
||||
ctok->state = CTokStateNumLitIntSuffixUL;
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateNumLitIntSuffixL:
|
||||
switch (*c) {
|
||||
case 'l':
|
||||
case 'L':
|
||||
ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLL;
|
||||
ctok->state = CTokStateNumLitIntSuffixLL;
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLU;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateNumLitIntSuffixLL:
|
||||
switch (*c) {
|
||||
case 'u':
|
||||
case 'U':
|
||||
ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLLU;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateNumLitIntSuffixUL:
|
||||
switch (*c) {
|
||||
case 'l':
|
||||
case 'L':
|
||||
ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLLU;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateIdentifier:
|
||||
switch (*c) {
|
||||
case IDENT:
|
||||
buf_append_char(&ctok->cur_tok->data.symbol, *c);
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateString:
|
||||
switch (*c) {
|
||||
case '\\':
|
||||
ctok->state = CTokStateCharEscape;
|
||||
break;
|
||||
case '\"':
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
break;
|
||||
default:
|
||||
buf_append_char(&ctok->cur_tok->data.str_lit, *c);
|
||||
}
|
||||
break;
|
||||
case CTokStateExpectChar:
|
||||
switch (*c) {
|
||||
case '\\':
|
||||
ctok->state = CTokStateCharEscape;
|
||||
break;
|
||||
case '\'':
|
||||
return mark_error(ctok);
|
||||
default:
|
||||
ctok->cur_tok->data.char_lit = *c;
|
||||
ctok->state = CTokStateExpectEndQuot;
|
||||
}
|
||||
break;
|
||||
case CTokStateCharEscape:
|
||||
switch (*c) {
|
||||
case '\'':
|
||||
case '"':
|
||||
case '?':
|
||||
case '\\':
|
||||
add_char(ctok, *c);
|
||||
break;
|
||||
case 'a':
|
||||
add_char(ctok, '\a');
|
||||
break;
|
||||
case 'b':
|
||||
add_char(ctok, '\b');
|
||||
break;
|
||||
case 'f':
|
||||
add_char(ctok, '\f');
|
||||
break;
|
||||
case 'n':
|
||||
add_char(ctok, '\n');
|
||||
break;
|
||||
case 'r':
|
||||
add_char(ctok, '\r');
|
||||
break;
|
||||
case 't':
|
||||
add_char(ctok, '\t');
|
||||
break;
|
||||
case 'v':
|
||||
add_char(ctok, '\v');
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
ctok->state = CTokStateStrOctal;
|
||||
ctok->cur_char = (uint8_t)(*c - '0');
|
||||
ctok->octal_index = 1;
|
||||
break;
|
||||
case 'x':
|
||||
ctok->state = CTokStateStrHex;
|
||||
ctok->cur_char = 0;
|
||||
break;
|
||||
case 'u':
|
||||
zig_panic("TODO unicode");
|
||||
break;
|
||||
case 'U':
|
||||
zig_panic("TODO Unicode");
|
||||
break;
|
||||
default:
|
||||
return mark_error(ctok);
|
||||
}
|
||||
break;
|
||||
case CTokStateStrHex: {
|
||||
uint8_t value = 0;
|
||||
switch (*c) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
value = *c - '0';
|
||||
break;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
value = (*c - 'a') + 10;
|
||||
break;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
value = (*c - 'A') + 10;
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
add_char(ctok, ctok->cur_char);
|
||||
continue;
|
||||
}
|
||||
// TODO @mul_with_overflow
|
||||
if (((long)ctok->cur_char) * 16 >= 256) {
|
||||
zig_panic("TODO str hex mul overflow");
|
||||
}
|
||||
ctok->cur_char = (uint8_t)(ctok->cur_char * (uint8_t)16);
|
||||
// TODO @add_with_overflow
|
||||
if (((long)ctok->cur_char) + (long)(value) >= 256) {
|
||||
zig_panic("TODO str hex add overflow");
|
||||
}
|
||||
ctok->cur_char = (uint8_t)(ctok->cur_char + value);
|
||||
break;
|
||||
}
|
||||
case CTokStateStrOctal:
|
||||
switch (*c) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
// TODO @mul_with_overflow
|
||||
if (((long)ctok->cur_char) * 8 >= 256) {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
ctok->cur_char = (uint8_t)(ctok->cur_char * (uint8_t)8);
|
||||
// TODO @add_with_overflow
|
||||
if (((long)ctok->cur_char) + (long)(*c - '0') >= 256) {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
ctok->cur_char = (uint8_t)(ctok->cur_char + (uint8_t)(*c - '0'));
|
||||
ctok->octal_index += 1;
|
||||
if (ctok->octal_index == 3) {
|
||||
add_char(ctok, ctok->cur_char);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
c -= 1;
|
||||
add_char(ctok, ctok->cur_char);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case CTokStateExpectEndQuot:
|
||||
switch (*c) {
|
||||
case '\'':
|
||||
end_token(ctok);
|
||||
ctok->state = CTokStateStart;
|
||||
break;
|
||||
default:
|
||||
return mark_error(ctok);
|
||||
}
|
||||
break;
|
||||
case CTokStateOpenComment:
|
||||
switch (*c) {
|
||||
case '/':
|
||||
ctok->state = CTokStateLineComment;
|
||||
break;
|
||||
case '*':
|
||||
ctok->state = CTokStateComment;
|
||||
break;
|
||||
default:
|
||||
return mark_error(ctok);
|
||||
}
|
||||
break;
|
||||
case CTokStateLineComment:
|
||||
if (*c == '\n') {
|
||||
ctok->state = CTokStateStart;
|
||||
goto found_end_of_macro;
|
||||
}
|
||||
break;
|
||||
case CTokStateComment:
|
||||
switch (*c) {
|
||||
case '*':
|
||||
ctok->state = CTokStateCommentStar;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CTokStateCommentStar:
|
||||
switch (*c) {
|
||||
case '/':
|
||||
ctok->state = CTokStateStart;
|
||||
break;
|
||||
case '*':
|
||||
break;
|
||||
default:
|
||||
ctok->state = CTokStateComment;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CTokStateBackslash:
|
||||
switch (*c) {
|
||||
case '\n':
|
||||
ctok->state = CTokStateStart;
|
||||
break;
|
||||
default:
|
||||
return mark_error(ctok);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
found_end_of_macro:
|
||||
|
||||
switch (ctok->state) {
|
||||
case CTokStateStart:
|
||||
break;
|
||||
case CTokStateIdentifier:
|
||||
case CTokStateDecimal:
|
||||
case CTokStateHex:
|
||||
case CTokStateOctal:
|
||||
case CTokStateGotZero:
|
||||
case CTokStateNumLitIntSuffixU:
|
||||
case CTokStateNumLitIntSuffixL:
|
||||
case CTokStateNumLitIntSuffixUL:
|
||||
case CTokStateNumLitIntSuffixLL:
|
||||
case CTokStateGotLt:
|
||||
end_token(ctok);
|
||||
break;
|
||||
case CTokStateFloat:
|
||||
case CTokStateFloatExp:
|
||||
end_float(ctok);
|
||||
break;
|
||||
case CTokStateExpectChar:
|
||||
case CTokStateExpectEndQuot:
|
||||
case CTokStateOpenComment:
|
||||
case CTokStateLineComment:
|
||||
case CTokStateComment:
|
||||
case CTokStateCommentStar:
|
||||
case CTokStateCharEscape:
|
||||
case CTokStateBackslash:
|
||||
case CTokStateString:
|
||||
case CTokStateExpSign:
|
||||
case CTokStateFloatExpFirst:
|
||||
case CTokStateStrHex:
|
||||
case CTokStateStrOctal:
|
||||
return mark_error(ctok);
|
||||
}
|
||||
|
||||
assert(ctok->cur_tok == nullptr);
|
||||
|
||||
begin_token(ctok, CTokIdEOF);
|
||||
end_token(ctok);
|
||||
}
|
||||
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Andrew Kelley
|
||||
*
|
||||
* This file is part of zig, which is MIT licensed.
|
||||
* See http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ZIG_C_TOKENIZER_HPP
|
||||
#define ZIG_C_TOKENIZER_HPP
|
||||
|
||||
#include "buffer.hpp"
|
||||
|
||||
enum CTokId {
|
||||
CTokIdCharLit,
|
||||
CTokIdStrLit,
|
||||
CTokIdNumLitInt,
|
||||
CTokIdNumLitFloat,
|
||||
CTokIdSymbol,
|
||||
CTokIdMinus,
|
||||
CTokIdLParen,
|
||||
CTokIdRParen,
|
||||
CTokIdEOF,
|
||||
CTokIdDot,
|
||||
CTokIdAsterisk,
|
||||
CTokIdBang,
|
||||
CTokIdTilde,
|
||||
CTokIdShl,
|
||||
CTokIdLt,
|
||||
};
|
||||
|
||||
enum CNumLitSuffix {
|
||||
CNumLitSuffixNone,
|
||||
CNumLitSuffixL,
|
||||
CNumLitSuffixU,
|
||||
CNumLitSuffixLU,
|
||||
CNumLitSuffixLL,
|
||||
CNumLitSuffixLLU,
|
||||
};
|
||||
|
||||
struct CNumLitInt {
|
||||
uint64_t x;
|
||||
CNumLitSuffix suffix;
|
||||
};
|
||||
|
||||
struct CTok {
|
||||
enum CTokId id;
|
||||
union {
|
||||
uint8_t char_lit;
|
||||
Buf str_lit;
|
||||
CNumLitInt num_lit_int;
|
||||
double num_lit_float;
|
||||
Buf symbol;
|
||||
} data;
|
||||
};
|
||||
|
||||
enum CTokState {
|
||||
CTokStateStart,
|
||||
CTokStateExpectChar,
|
||||
CTokStateCharEscape,
|
||||
CTokStateExpectEndQuot,
|
||||
CTokStateOpenComment,
|
||||
CTokStateLineComment,
|
||||
CTokStateComment,
|
||||
CTokStateCommentStar,
|
||||
CTokStateBackslash,
|
||||
CTokStateString,
|
||||
CTokStateIdentifier,
|
||||
CTokStateDecimal,
|
||||
CTokStateOctal,
|
||||
CTokStateGotZero,
|
||||
CTokStateHex,
|
||||
CTokStateFloat,
|
||||
CTokStateExpSign,
|
||||
CTokStateFloatExp,
|
||||
CTokStateFloatExpFirst,
|
||||
CTokStateStrHex,
|
||||
CTokStateStrOctal,
|
||||
CTokStateNumLitIntSuffixU,
|
||||
CTokStateNumLitIntSuffixL,
|
||||
CTokStateNumLitIntSuffixLL,
|
||||
CTokStateNumLitIntSuffixUL,
|
||||
CTokStateGotLt,
|
||||
};
|
||||
|
||||
struct CTokenize {
|
||||
ZigList<CTok> tokens;
|
||||
CTokState state;
|
||||
bool error;
|
||||
CTok *cur_tok;
|
||||
Buf buf;
|
||||
uint8_t cur_char;
|
||||
int octal_index;
|
||||
};
|
||||
|
||||
void tokenize_c_macro(CTokenize *ctok, const uint8_t *c);
|
||||
|
||||
#endif
|
||||
@ -15,7 +15,6 @@
|
||||
#include "hash_map.hpp"
|
||||
#include "ir.hpp"
|
||||
#include "os.hpp"
|
||||
#include "translate_c.hpp"
|
||||
#include "target.hpp"
|
||||
#include "util.hpp"
|
||||
#include "zig_llvm.h"
|
||||
@ -9090,7 +9089,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
|
||||
|
||||
}
|
||||
|
||||
void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation) {
|
||||
void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file) {
|
||||
Error err;
|
||||
Buf *src_basename = buf_alloc();
|
||||
Buf *src_dirname = buf_alloc();
|
||||
@ -9103,10 +9102,6 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
|
||||
|
||||
init(g);
|
||||
|
||||
TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ?
|
||||
TranslateModeImport : TranslateModeTranslate;
|
||||
|
||||
|
||||
ZigList<const char *> clang_argv = {0};
|
||||
add_cc_args(g, clang_argv, nullptr, true);
|
||||
|
||||
@ -9126,15 +9121,9 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
|
||||
Stage2ErrorMsg *errors_ptr;
|
||||
size_t errors_len;
|
||||
Stage2Ast *ast;
|
||||
AstNode *root_node;
|
||||
|
||||
if (use_userland_implementation) {
|
||||
err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
|
||||
&clang_argv.at(0), &clang_argv.last(), resources_path);
|
||||
} else {
|
||||
err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(),
|
||||
trans_mode, resources_path);
|
||||
}
|
||||
err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
|
||||
&clang_argv.at(0), &clang_argv.last(), resources_path);
|
||||
|
||||
if (err == ErrorCCompileErrors && errors_len > 0) {
|
||||
for (size_t i = 0; i < errors_len; i += 1) {
|
||||
@ -9158,12 +9147,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (use_userland_implementation) {
|
||||
stage2_render_ast(ast, out_file);
|
||||
} else {
|
||||
ast_render(out_file, root_node, 4);
|
||||
}
|
||||
stage2_render_ast(ast, out_file);
|
||||
}
|
||||
|
||||
static void update_test_functions_builtin_decl(CodeGen *g) {
|
||||
|
||||
@ -54,7 +54,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
|
||||
void codegen_add_assembly(CodeGen *g, Buf *path);
|
||||
void codegen_add_object(CodeGen *g, Buf *object_path);
|
||||
|
||||
void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation);
|
||||
void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file);
|
||||
|
||||
Buf *codegen_generate_builtin_source(CodeGen *g);
|
||||
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#include "os.hpp"
|
||||
#include "range_set.hpp"
|
||||
#include "softfloat.hpp"
|
||||
#include "translate_c.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
#include <errno.h>
|
||||
@ -23755,14 +23754,14 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
|
||||
|
||||
clang_argv.append(nullptr); // to make the [start...end] argument work
|
||||
|
||||
AstNode *root_node;
|
||||
Stage2ErrorMsg *errors_ptr;
|
||||
size_t errors_len;
|
||||
Stage2Ast *ast;
|
||||
|
||||
const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir);
|
||||
|
||||
if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len,
|
||||
&clang_argv.at(0), &clang_argv.last(), TranslateModeImport, resources_path)))
|
||||
if ((err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
|
||||
&clang_argv.at(0), &clang_argv.last(), resources_path)))
|
||||
{
|
||||
if (err != ErrorCCompileErrors) {
|
||||
ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
|
||||
@ -23813,7 +23812,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
|
||||
buf_sprintf("C import failed: unable to open output file: %s", strerror(errno)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
ast_render(out_file, root_node, 4);
|
||||
stage2_render_ast(ast, out_file);
|
||||
if (fclose(out_file) != 0) {
|
||||
ir_add_error_node(ira, node,
|
||||
buf_sprintf("C import failed: unable to write to output file: %s", strerror(errno)));
|
||||
|
||||
16
src/main.cpp
16
src/main.cpp
@ -243,7 +243,6 @@ enum Cmd {
|
||||
CmdTargets,
|
||||
CmdTest,
|
||||
CmdTranslateC,
|
||||
CmdTranslateCUserland,
|
||||
CmdVersion,
|
||||
CmdZen,
|
||||
CmdLibC,
|
||||
@ -960,8 +959,6 @@ int main(int argc, char **argv) {
|
||||
cmd = CmdLibC;
|
||||
} else if (strcmp(arg, "translate-c") == 0) {
|
||||
cmd = CmdTranslateC;
|
||||
} else if (strcmp(arg, "translate-c-2") == 0) {
|
||||
cmd = CmdTranslateCUserland;
|
||||
} else if (strcmp(arg, "test") == 0) {
|
||||
cmd = CmdTest;
|
||||
out_type = OutTypeExe;
|
||||
@ -978,7 +975,6 @@ int main(int argc, char **argv) {
|
||||
case CmdBuild:
|
||||
case CmdRun:
|
||||
case CmdTranslateC:
|
||||
case CmdTranslateCUserland:
|
||||
case CmdTest:
|
||||
case CmdLibC:
|
||||
if (!in_file) {
|
||||
@ -1112,7 +1108,6 @@ int main(int argc, char **argv) {
|
||||
case CmdRun:
|
||||
case CmdBuild:
|
||||
case CmdTranslateC:
|
||||
case CmdTranslateCUserland:
|
||||
case CmdTest:
|
||||
{
|
||||
if (cmd == CmdBuild && !in_file && objects.length == 0 &&
|
||||
@ -1124,7 +1119,7 @@ int main(int argc, char **argv) {
|
||||
" * --object argument\n"
|
||||
" * --c-source argument\n");
|
||||
return print_error_usage(arg0);
|
||||
} else if ((cmd == CmdTranslateC || cmd == CmdTranslateCUserland ||
|
||||
} else if ((cmd == CmdTranslateC ||
|
||||
cmd == CmdTest || cmd == CmdRun) && !in_file)
|
||||
{
|
||||
fprintf(stderr, "Expected source file argument.\n");
|
||||
@ -1136,7 +1131,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
assert(cmd != CmdBuild || out_type != OutTypeUnknown);
|
||||
|
||||
bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC || cmd == CmdTranslateCUserland);
|
||||
bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC);
|
||||
|
||||
if (cmd == CmdRun) {
|
||||
out_name = "run";
|
||||
@ -1170,8 +1165,7 @@ int main(int argc, char **argv) {
|
||||
return print_error_usage(arg0);
|
||||
}
|
||||
|
||||
Buf *zig_root_source_file = (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) ?
|
||||
nullptr : in_file_buf;
|
||||
Buf *zig_root_source_file = cmd == CmdTranslateC ? nullptr : in_file_buf;
|
||||
|
||||
if (cmd == CmdRun && buf_out_name == nullptr) {
|
||||
buf_out_name = buf_create_from_str("run");
|
||||
@ -1336,8 +1330,8 @@ int main(int argc, char **argv) {
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
} else if (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) {
|
||||
codegen_translate_c(g, in_file_buf, stdout, cmd == CmdTranslateCUserland);
|
||||
} else if (cmd == CmdTranslateC) {
|
||||
codegen_translate_c(g, in_file_buf, stdout);
|
||||
if (timing_info)
|
||||
codegen_print_timing_report(g, stderr);
|
||||
return main_exit(root_progress_node, EXIT_SUCCESS);
|
||||
|
||||
5156
src/translate_c.cpp
5156
src/translate_c.cpp
File diff suppressed because it is too large
Load Diff
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Andrew Kelley
|
||||
*
|
||||
* This file is part of zig, which is MIT licensed.
|
||||
* See http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ZIG_PARSEC_HPP
|
||||
#define ZIG_PARSEC_HPP
|
||||
|
||||
#include "all_types.hpp"
|
||||
|
||||
enum TranslateMode {
|
||||
TranslateModeImport,
|
||||
TranslateModeTranslate,
|
||||
};
|
||||
|
||||
Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
|
||||
Stage2ErrorMsg **errors_ptr, size_t *errors_len,
|
||||
const char **args_begin, const char **args_end,
|
||||
TranslateMode mode, const char *resources_path);
|
||||
|
||||
#endif
|
||||
@ -1422,7 +1422,6 @@ pub const TranslateCContext = struct {
|
||||
sources: ArrayList(SourceFile),
|
||||
expected_lines: ArrayList([]const u8),
|
||||
allow_warnings: bool,
|
||||
stage2: bool,
|
||||
|
||||
const SourceFile = struct {
|
||||
filename: []const u8,
|
||||
@ -1475,7 +1474,7 @@ pub const TranslateCContext = struct {
|
||||
var zig_args = ArrayList([]const u8).init(b.allocator);
|
||||
zig_args.append(b.zig_exe) catch unreachable;
|
||||
|
||||
const translate_c_cmd = if (self.case.stage2) "translate-c-2" else "translate-c";
|
||||
const translate_c_cmd = "translate-c";
|
||||
zig_args.append(translate_c_cmd) catch unreachable;
|
||||
zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
|
||||
|
||||
@ -1583,7 +1582,6 @@ pub const TranslateCContext = struct {
|
||||
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
|
||||
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
|
||||
.allow_warnings = allow_warnings,
|
||||
.stage2 = false,
|
||||
};
|
||||
|
||||
tc.addSourceFile(filename, source);
|
||||
@ -1604,53 +1602,6 @@ pub const TranslateCContext = struct {
|
||||
self.addCase(tc);
|
||||
}
|
||||
|
||||
pub fn addC(
|
||||
self: *TranslateCContext,
|
||||
name: []const u8,
|
||||
source: []const u8,
|
||||
expected_lines: []const []const u8,
|
||||
) void {
|
||||
const tc = self.create(false, "source.c", name, source, expected_lines);
|
||||
self.addCase(tc);
|
||||
}
|
||||
|
||||
pub fn add_both(
|
||||
self: *TranslateCContext,
|
||||
name: []const u8,
|
||||
source: []const u8,
|
||||
expected_lines: []const []const u8,
|
||||
) void {
|
||||
for ([_]bool{ false, true }) |stage2| {
|
||||
const tc = self.create(false, "source.h", name, source, expected_lines);
|
||||
tc.stage2 = stage2;
|
||||
self.addCase(tc);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addC_both(
|
||||
self: *TranslateCContext,
|
||||
name: []const u8,
|
||||
source: []const u8,
|
||||
expected_lines: []const []const u8,
|
||||
) void {
|
||||
for ([_]bool{ false, true }) |stage2| {
|
||||
const tc = self.create(false, "source.c", name, source, expected_lines);
|
||||
tc.stage2 = stage2;
|
||||
self.addCase(tc);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_2(
|
||||
self: *TranslateCContext,
|
||||
name: []const u8,
|
||||
source: []const u8,
|
||||
expected_lines: []const []const u8,
|
||||
) void {
|
||||
const tc = self.create(false, "source.h", name, source, expected_lines);
|
||||
tc.stage2 = true;
|
||||
self.addCase(tc);
|
||||
}
|
||||
|
||||
pub fn addAllowWarnings(
|
||||
self: *TranslateCContext,
|
||||
name: []const u8,
|
||||
@ -1664,7 +1615,7 @@ pub const TranslateCContext = struct {
|
||||
pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
|
||||
const b = self.b;
|
||||
|
||||
const translate_c_cmd = if (case.stage2) "translate-c-2" else "translate-c";
|
||||
const translate_c_cmd = "translate-c";
|
||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", .{ translate_c_cmd, case.name }) catch unreachable;
|
||||
if (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
|
||||
|
||||
1265
test/translate_c.zig
1265
test/translate_c.zig
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user