static string[] cc_options;
static string dump_tree;
static bool save_temps;
+ [CCode (array_length = false, array_null_terminated = true)]
+ [NoArrayLength]
+ static string[] defines;
static bool quiet_mode;
private CodeContext context;
{ "output", 'o', 0, OptionArg.FILENAME, ref output, "Place output in file FILE", "FILE" },
{ "debug", 'g', 0, OptionArg.NONE, ref debug, "Produce debug information", null },
{ "thread", 0, 0, OptionArg.NONE, ref thread, "Enable multithreading support", null },
+ { "define", 'D', 0, OptionArg.STRING_ARRAY, ref defines, "Define SYMBOL", "SYMBOL..." },
{ "disable-assert", 0, 0, OptionArg.NONE, ref disable_assert, "Disable assertions", null },
{ "enable-checking", 0, 0, OptionArg.NONE, ref enable_checking, "Enable additional run-time checks", null },
{ "enable-deprecated", 0, 0, OptionArg.NONE, ref deprecated, "Enable deprecated features", null },
context.thread = thread;
context.save_temps = save_temps;
+ if (defines != null) {
+ foreach (string define in defines) {
+ context.add_define (define);
+ }
+ }
+
int glib_major = 2;
int glib_minor = 12;
if (target_glib != null && target_glib.scanf ("%d.%d", out glib_major, out glib_minor) != 2) {
string _comment;
+ Conditional[] conditional_stack;
+
+ struct Conditional {
+ public bool matched;
+ public bool else_found;
+ public bool skip_section;
+ }
+
public Scanner (SourceFile source_file) {
this.source_file = source_file;
return true;
}
+ bool pp_whitespace () {
+ bool found = false;
+ while (current < end && current[0] == ' ') {
+ found = true;
+ current++;
+ column++;
+ }
+ return found;
+ }
+
+ void pp_directive () {
+ do {
+ current++;
+ column++;
+ } while (current < end && current[0] == ' ');
+
+ char* begin = current;
+ int len = 0;
+ while (current < end && current[0].isalnum ()) {
+ current++;
+ column++;
+ len++;
+ }
+
+ if (len == 2 && matches (begin, "if")) {
+ parse_pp_if ();
+ } else if (len == 4 && matches (begin, "elif")) {
+ parse_pp_elif ();
+ } else if (len == 4 && matches (begin, "else")) {
+ parse_pp_else ();
+ } else if (len == 5 && matches (begin, "endif")) {
+ parse_pp_endif ();
+ } else {
+ Report.error (new SourceReference (source_file, line, column - len, line, column), "syntax error, invalid preprocessing directive");
+ }
+
+ if (conditional_stack.length > 0
+ && conditional_stack[conditional_stack.length - 1].skip_section) {
+ // skip lines until next preprocessing directive
+ bool bol = false;
+ while (current < end) {
+ if (bol && current[0] == '#') {
+ return;
+ }
+ if (current[0] == '\n') {
+ line++;
+ column = 0;
+ bol = true;
+ } else if (current[0] != ' ') {
+ bol = false;
+ }
+ current++;
+ column++;
+ }
+ }
+ }
+
+ void pp_eol () {
+ pp_whitespace ();
+ if (current >= end || current[0] != '\n') {
+ Report.error (new SourceReference (source_file, line, column, line, column), "syntax error, expected newline");
+ }
+ }
+
+ void parse_pp_if () {
+ pp_whitespace ();
+
+ bool condition = parse_pp_expression ();
+
+ pp_eol ();
+
+ conditional_stack += Conditional ();
+
+ if (condition && (conditional_stack.length == 1 || !conditional_stack[conditional_stack.length - 2].skip_section)) {
+ // condition true => process code within if
+ conditional_stack[conditional_stack.length - 1].matched = true;
+ } else {
+ // skip lines until next preprocessing directive
+ conditional_stack[conditional_stack.length - 1].skip_section = true;
+ }
+ }
+
+ void parse_pp_elif () {
+ pp_whitespace ();
+
+ bool condition = parse_pp_expression ();
+
+ pp_eol ();
+
+ if (conditional_stack.length == 0 || conditional_stack[conditional_stack.length - 1].else_found) {
+ Report.error (new SourceReference (source_file, line, column, line, column), "syntax error, unexpected #elif");
+ return;
+ }
+
+ if (condition && !conditional_stack[conditional_stack.length - 1].matched
+ && (conditional_stack.length == 1 || !conditional_stack[conditional_stack.length - 2].skip_section)) {
+ // condition true => process code within if
+ conditional_stack[conditional_stack.length - 1].matched = true;
+ conditional_stack[conditional_stack.length - 1].skip_section = false;
+ } else {
+ // skip lines until next preprocessing directive
+ conditional_stack[conditional_stack.length - 1].skip_section = true;
+ }
+ }
+
+ void parse_pp_else () {
+ pp_eol ();
+
+ if (conditional_stack.length == 0 || conditional_stack[conditional_stack.length - 1].else_found) {
+ Report.error (new SourceReference (source_file, line, column, line, column), "syntax error, unexpected #else");
+ return;
+ }
+
+ if (!conditional_stack[conditional_stack.length - 1].matched
+ && (conditional_stack.length == 1 || !conditional_stack[conditional_stack.length - 2].skip_section)) {
+ // condition true => process code within if
+ conditional_stack[conditional_stack.length - 1].matched = true;
+ conditional_stack[conditional_stack.length - 1].skip_section = false;
+ } else {
+ // skip lines until next preprocessing directive
+ conditional_stack[conditional_stack.length - 1].skip_section = true;
+ }
+ }
+
+ void parse_pp_endif () {
+ pp_eol ();
+
+ if (conditional_stack.length == 0) {
+ Report.error (new SourceReference (source_file, line, column, line, column), "syntax error, unexpected #endif");
+ return;
+ }
+
+ conditional_stack.length--;
+ }
+
+ bool parse_pp_symbol () {
+ int len = 0;
+ while (current < end && is_ident_char (current[0])) {
+ current++;
+ column++;
+ len++;
+ }
+
+ if (len == 0) {
+ Report.error (new SourceReference (source_file, line, column, line, column), "syntax error, expected identifier");
+ return false;
+ }
+
+ string identifier = ((string) (current - len)).ndup (len);
+ bool defined;
+ if (identifier == "true") {
+ defined = true;
+ } else if (identifier == "false") {
+ defined = false;
+ } else {
+ defined = source_file.context.is_defined (identifier);
+ }
+
+ return defined;
+ }
+
+ bool parse_pp_primary_expression () {
+ if (current >= end) {
+ Report.error (new SourceReference (source_file, line, column, line, column), "syntax error, expected identifier");
+ } else if (is_ident_char (current[0])) {
+ return parse_pp_symbol ();
+ } else if (current[0] == '(') {
+ current++;
+ column++;
+ pp_whitespace ();
+ bool result = parse_pp_expression ();
+ pp_whitespace ();
+ if (current < end && current[0] == ')') {
+ current++;
+ column++;
+ } else {
+ Report.error (new SourceReference (source_file, line, column, line, column), "syntax error, expected `)'");
+ }
+ return result;
+ } else {
+ Report.error (new SourceReference (source_file, line, column, line, column), "syntax error, expected identifier");
+ }
+ return false;
+ }
+
+ bool parse_pp_unary_expression () {
+ if (current < end && current[0] == '!') {
+ current++;
+ column++;
+ pp_whitespace ();
+ return !parse_pp_unary_expression ();
+ }
+
+ return parse_pp_primary_expression ();
+ }
+
+ bool parse_pp_equality_expression () {
+ bool left = parse_pp_unary_expression ();
+ pp_whitespace ();
+ while (true) {
+ if (current < end - 1 && current[0] == '=' && current[1] == '=') {
+ current += 2;
+ column += 2;
+ pp_whitespace ();
+ bool right = parse_pp_unary_expression ();
+ left = (left == right);
+ } else if (current < end - 1 && current[0] == '!' && current[1] == '=') {
+ current += 2;
+ column += 2;
+ pp_whitespace ();
+ bool right = parse_pp_unary_expression ();
+ left = (left != right);
+ } else {
+ break;
+ }
+ }
+ return left;
+ }
+
+ bool parse_pp_and_expression () {
+ bool left = parse_pp_equality_expression ();
+ pp_whitespace ();
+ while (current < end - 1 && current[0] == '&' && current[1] == '&') {
+ current += 2;
+ column += 2;
+ pp_whitespace ();
+ bool right = parse_pp_equality_expression ();
+ left = left && right;
+ }
+ return left;
+ }
+
+ bool parse_pp_or_expression () {
+ bool left = parse_pp_and_expression ();
+ pp_whitespace ();
+ while (current < end - 1 && current[0] == '|' && current[1] == '|') {
+ current += 2;
+ column += 2;
+ pp_whitespace ();
+ bool right = parse_pp_and_expression ();
+ left = left || right;
+ }
+ return left;
+ }
+
+ bool parse_pp_expression () {
+ return parse_pp_or_expression ();
+ }
+
bool whitespace () {
bool found = false;
+ bool bol = (column == 1);
while (current < end && current[0].isspace ()) {
if (current[0] == '\n') {
line++;
column = 0;
+ bol = true;
}
found = true;
current++;
column++;
}
+ if (bol && current[0] == '#') {
+ pp_directive ();
+ return true;
+ }
return found;
}