+ case "endif":\r
+ if (ifstack == null || ifstack.Count == 0){\r
+ Error_UnexpectedDirective ("no #if for this #endif");\r
+ return true;\r
+ } else {\r
+ ifstack.Pop ();\r
+ if (ifstack.Count == 0)\r
+ return true;\r
+ else {\r
+ int state = (int) ifstack.Peek ();\r
+\r
+ if ((state & TAKING) != 0)\r
+ return true;\r
+ else\r
+ return false;\r
+ }\r
+ }\r
+\r
+ case "elif":\r
+ if (ifstack == null || ifstack.Count == 0){\r
+ Error_UnexpectedDirective ("no #if for this #elif");\r
+ return true;\r
+ } else {\r
+ int state = (int) ifstack.Peek ();\r
+\r
+ if ((state & ELSE_SEEN) != 0){\r
+ Error_UnexpectedDirective ("#elif not valid after #else");\r
+ return true;\r
+ }\r
+\r
+ if ((state & (TAKEN_BEFORE | TAKING)) != 0)\r
+ return false;\r
+\r
+ if (eval (arg) && ((state & PARENT_TAKING) != 0)){\r
+ state = (int) ifstack.Pop ();\r
+ ifstack.Push (state | TAKING | TAKEN_BEFORE);\r
+ return true;\r
+ } else \r
+ return false;\r
+ }\r
+\r
+ case "else":\r
+ if (ifstack == null || ifstack.Count == 0){\r
+ Report.Error (\r
+ 1028, Location,\r
+ "Unexpected processor directive (no #if for this #else)");\r
+ return true;\r
+ } else {\r
+ int state = (int) ifstack.Peek ();\r
+\r
+ if ((state & ELSE_SEEN) != 0){\r
+ Error_UnexpectedDirective ("#else within #else");\r
+ return true;\r
+ }\r
+\r
+ ifstack.Pop ();\r
+\r
+ bool ret;\r
+ if ((state & TAKEN_BEFORE) == 0){\r
+ ret = ((state & PARENT_TAKING) != 0);\r
+ } else\r
+ ret = false;\r
+ \r
+ if (ret)\r
+ state |= TAKING;\r
+ else\r
+ state &= ~TAKING;\r
+ \r
+ ifstack.Push (state | ELSE_SEEN);\r
+ \r
+ return ret;\r
+ }\r
+ }\r
+\r
+ //\r
+ // These are only processed if we are in a `taking' block\r
+ //\r
+ if (!caller_is_taking)\r
+ return false;\r
+ \r
+ switch (cmd){\r
+ case "define":\r
+ if (any_token_seen){\r
+ Error_TokensSeen ();\r
+ return true;\r
+ }\r
+ PreProcessDefinition (true, arg);\r
+ return true;\r
+\r
+ case "undef":\r
+ if (any_token_seen){\r
+ Error_TokensSeen ();\r
+ return true;\r
+ }\r
+ PreProcessDefinition (false, arg);\r
+ return true;\r
+\r
+ case "error":\r
+ Report.Error (1029, Location, "#error: '" + arg + "'");\r
+ return true;\r
+\r
+ case "warning":\r
+ Report.Warning (1030, Location, "#warning: '" + arg + "'");\r
+ return true;\r
+ }\r
+\r
+ Report.Error (1024, Location, "Preprocessor directive expected (got: " + cmd + ")");\r
+ return true;\r
+\r
+ }\r
+\r
+ private int consume_string (bool quoted) \r
+ {\r
+ int c;\r
+ string_builder.Length = 0;\r
+ \r
+ while ((c = getChar ()) != -1){\r
+ if (c == '"'){\r
+ if (quoted && peekChar () == '"'){\r
+ string_builder.Append ((char) c);\r
+ getChar ();\r
+ continue;\r
+ } else {\r
+ val = string_builder.ToString ();\r
+ return Token.LITERAL_STRING;\r
+ }\r
+ }\r
+\r
+ if (c == '\n'){\r
+ if (!quoted)\r
+ Report.Error (1010, Location, "Newline in constant");\r
+ line++;\r
+ ref_line++;\r
+ col = 0;\r
+ } else\r
+ col++;\r
+\r
+ if (!quoted){\r
+ c = escape (c);\r
+ if (c == -1)\r
+ return Token.ERROR;\r
+ }\r
+ string_builder.Append ((char) c);\r
+ }\r
+\r
+ Report.Error (1039, Location, "Unterminated string literal");\r
+ return Token.EOF;\r
+ }\r
+\r
+ private int consume_identifier (int s, bool quoted) \r
+ {\r
+ int pos = 1;\r
+ int c;\r
+ \r
+ id_builder [0] = (char) s;\r
+ \r
+ while ((c = reader.Read ()) != -1) {\r
+ if (is_identifier_part_character ((char) c)){\r
+ if (pos == max_id_size){\r
+ Report.Error (645, Location, "Identifier too long (limit is 512 chars)");\r
+ return Token.ERROR;\r
+ }\r
+ \r
+ id_builder [pos++] = (char) c;\r
+ putback_char = -1;\r
+ col++;\r
+ } else {\r
+ putback_char = c;\r
+ break;\r
+ }\r
+ }\r
+\r
+ string ids = new String (id_builder, 0, pos);\r
+\r
+ if (s >= 'a'){\r
+ int keyword = GetKeyword (ids);\r
+ if (keyword == -1 || quoted){\r
+ val = ids;\r
+ return Token.IDENTIFIER;\r
+ }\r
+ return keyword;\r
+ }\r
+ val = ids;\r
+ return Token.IDENTIFIER;\r
+ }\r
+ \r
+ public int xtoken ()\r
+ {\r
+ int t;\r
+ bool doread = false;\r
+ int c;\r
+\r
+ val = null;\r
+ // optimization: eliminate col and implement #directive semantic correctly.\r
+ for (;(c = getChar ()) != -1; col++) {\r
+ if (c == ' ' || c == '\t' || c == '\f' || c == '\v' || c == '\r' || c == 0xa0){\r
+ \r
+ if (c == '\t')\r
+ col = (((col + 8) / 8) * 8) - 1;\r
+ continue;\r
+ }\r