📄 gscanner.c
字号:
scanner->value = scanner->next_value; scanner->line = scanner->next_line; scanner->position = scanner->next_position; scanner->next_token = G_TOKEN_NONE; } else g_scanner_get_token_i (scanner, &scanner->token, &scanner->value, &scanner->line, &scanner->position); return scanner->token;}GTokenTypeg_scanner_cur_token (GScanner *scanner){ g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF); return scanner->token;}GTokenValueg_scanner_cur_value (GScanner *scanner){ GTokenValue v; v.v_int = 0; g_return_val_if_fail (scanner != NULL, v); /* MSC isn't capable of handling return scanner->value; ? */ v = scanner->value; return v;}guintg_scanner_cur_line (GScanner *scanner){ g_return_val_if_fail (scanner != NULL, 0); return scanner->line;}guintg_scanner_cur_position (GScanner *scanner){ g_return_val_if_fail (scanner != NULL, 0); return scanner->position;}gbooleang_scanner_eof (GScanner *scanner){ g_return_val_if_fail (scanner != NULL, TRUE); return scanner->token == G_TOKEN_EOF || scanner->token == G_TOKEN_ERROR;}voidg_scanner_input_file (GScanner *scanner, gint input_fd){ g_return_if_fail (scanner != NULL); g_return_if_fail (input_fd >= 0); if (scanner->input_fd >= 0) g_scanner_sync_file_offset (scanner); scanner->token = G_TOKEN_NONE; scanner->value.v_int = 0; scanner->line = 1; scanner->position = 0; scanner->next_token = G_TOKEN_NONE; scanner->input_fd = input_fd; scanner->text = NULL; scanner->text_end = NULL; if (!scanner->buffer) scanner->buffer = g_new (gchar, READ_BUFFER_SIZE + 1);}voidg_scanner_input_text (GScanner *scanner, const gchar *text, guint text_len){ g_return_if_fail (scanner != NULL); if (text_len) g_return_if_fail (text != NULL); else text = NULL; if (scanner->input_fd >= 0) g_scanner_sync_file_offset (scanner); scanner->token = G_TOKEN_NONE; scanner->value.v_int = 0; scanner->line = 1; scanner->position = 0; scanner->next_token = G_TOKEN_NONE; scanner->input_fd = -1; scanner->text = text; scanner->text_end = text + text_len; if (scanner->buffer) { g_free (scanner->buffer); scanner->buffer = NULL; }}static gucharg_scanner_peek_next_char (GScanner *scanner){ if (scanner->text < scanner->text_end) { return *scanner->text; } else if (scanner->input_fd >= 0) { gint count; gchar *buffer; buffer = scanner->buffer; do { count = read (scanner->input_fd, buffer, READ_BUFFER_SIZE); } while (count == -1 && (errno == EINTR || errno == EAGAIN)); if (count < 1) { scanner->input_fd = -1; return 0; } else { scanner->text = buffer; scanner->text_end = buffer + count; return *buffer; } } else return 0;}voidg_scanner_sync_file_offset (GScanner *scanner){ g_return_if_fail (scanner != NULL); /* for file input, rewind the filedescriptor to the current * buffer position and blow the file read ahead buffer. usefull for * third party uses of our filedescriptor, which hooks onto the current * scanning position. */ if (scanner->input_fd >= 0 && scanner->text_end > scanner->text) { gint buffered; buffered = scanner->text_end - scanner->text; if (lseek (scanner->input_fd, - buffered, SEEK_CUR) >= 0) { /* we succeeded, blow our buffer's contents now */ scanner->text = NULL; scanner->text_end = NULL; } else errno = 0; }}static gucharg_scanner_get_char (GScanner *scanner, guint *line_p, guint *position_p){ guchar fchar; if (scanner->text < scanner->text_end) fchar = *(scanner->text++); else if (scanner->input_fd >= 0) { gint count; gchar *buffer; buffer = scanner->buffer; do { count = read (scanner->input_fd, buffer, READ_BUFFER_SIZE); } while (count == -1 && (errno == EINTR || errno == EAGAIN)); if (count < 1) { scanner->input_fd = -1; fchar = 0; } else { scanner->text = buffer + 1; scanner->text_end = buffer + count; fchar = *buffer; if (!fchar) { g_scanner_sync_file_offset (scanner); scanner->text_end = scanner->text; scanner->input_fd = -1; } } } else fchar = 0; if (fchar == '\n') { (*position_p) = 0; (*line_p)++; } else if (fchar) { (*position_p)++; } return fchar;}voidg_scanner_unexp_token (GScanner *scanner, GTokenType expected_token, const gchar *identifier_spec, const gchar *symbol_spec, const gchar *symbol_name, const gchar *message, gint is_error){ gchar *token_string; guint token_string_len; gchar *expected_string; guint expected_string_len; gchar *message_prefix; gboolean print_unexp; void (*msg_handler) (GScanner*, const gchar*, ...); g_return_if_fail (scanner != NULL); if (is_error) msg_handler = g_scanner_error; else msg_handler = g_scanner_warn; if (!identifier_spec) identifier_spec = "identifier"; if (!symbol_spec) symbol_spec = "symbol"; token_string_len = 56; token_string = g_new (gchar, token_string_len + 1); expected_string_len = 64; expected_string = g_new (gchar, expected_string_len + 1); print_unexp = TRUE; switch (scanner->token) { case G_TOKEN_EOF: g_snprintf (token_string, token_string_len, "end of file"); break; default: if (scanner->token >= 1 && scanner->token <= 255) { if ((scanner->token >= ' ' && scanner->token <= '~') || strchr (scanner->config->cset_identifier_first, scanner->token) || strchr (scanner->config->cset_identifier_nth, scanner->token)) g_snprintf (token_string, token_string_len, "character `%c'", scanner->token); else g_snprintf (token_string, token_string_len, "character `\\%o'", scanner->token); break; } else if (!scanner->config->symbol_2_token) { g_snprintf (token_string, token_string_len, "(unknown) token <%d>", scanner->token); break; } /* fall through */ case G_TOKEN_SYMBOL: if (expected_token == G_TOKEN_SYMBOL || (scanner->config->symbol_2_token && expected_token > G_TOKEN_LAST)) print_unexp = FALSE; if (symbol_name) g_snprintf (token_string, token_string_len, "%s%s `%s'", print_unexp ? "" : "invalid ", symbol_spec, symbol_name); else g_snprintf (token_string, token_string_len, "%s%s", print_unexp ? "" : "invalid ", symbol_spec); break; case G_TOKEN_ERROR: print_unexp = FALSE; expected_token = G_TOKEN_NONE; switch (scanner->value.v_error) { case G_ERR_UNEXP_EOF: g_snprintf (token_string, token_string_len, "scanner: unexpected end of file"); break; case G_ERR_UNEXP_EOF_IN_STRING: g_snprintf (token_string, token_string_len, "scanner: unterminated string constant"); break; case G_ERR_UNEXP_EOF_IN_COMMENT: g_snprintf (token_string, token_string_len, "scanner: unterminated comment"); break; case G_ERR_NON_DIGIT_IN_CONST: g_snprintf (token_string, token_string_len, "scanner: non digit in constant"); break; case G_ERR_FLOAT_RADIX: g_snprintf (token_string, token_string_len, "scanner: invalid radix for floating constant"); break; case G_ERR_FLOAT_MALFORMED: g_snprintf (token_string, token_string_len, "scanner: malformed floating constant"); break; case G_ERR_DIGIT_RADIX: g_snprintf (token_string, token_string_len, "scanner: digit is beyond radix"); break; case G_ERR_UNKNOWN: default: g_snprintf (token_string, token_string_len, "scanner: unknown error"); break; } break; case G_TOKEN_CHAR: g_snprintf (token_string, token_string_len, "character `%c'", scanner->value.v_char); break; case G_TOKEN_IDENTIFIER: case G_TOKEN_IDENTIFIER_NULL: if (expected_token == G_TOKEN_IDENTIFIER || expected_token == G_TOKEN_IDENTIFIER_NULL) print_unexp = FALSE; g_snprintf (token_string, token_string_len, "%s%s `%s'", print_unexp ? "" : "invalid ", identifier_spec, scanner->token == G_TOKEN_IDENTIFIER ? scanner->value.v_string : "null"); break; case G_TOKEN_BINARY: case G_TOKEN_OCTAL: case G_TOKEN_INT: case G_TOKEN_HEX: g_snprintf (token_string, token_string_len, "number `%lu'", scanner->value.v_int); break; case G_TOKEN_FLOAT: g_snprintf (token_string, token_string_len, "number `%.3f'", scanner->value.v_float); break; case G_TOKEN_STRING: if (expected_token == G_TOKEN_STRING) print_unexp = FALSE; g_snprintf (token_string, token_string_len, "%s%sstring constant \"%s\"", print_unexp ? "" : "invalid ", scanner->value.v_string[0] == 0 ? "empty " : "", scanner->value.v_string); token_string[token_string_len - 2] = '"'; token_string[token_string_len - 1] = 0; break; case G_TOKEN_COMMENT_SINGLE: case G_TOKEN_COMMENT_MULTI: g_snprintf (token_string, token_string_len, "comment"); break; case G_TOKEN_NONE: /* somehow the user's parsing code is screwed, there isn't much * we can do about it. * Note, a common case to trigger this is * g_scanner_peek_next_token(); g_scanner_unexp_token(); * without an intermediate g_scanner_get_next_token(). */ g_assert_not_reached (); break; } switch (expected_token) { gboolean need_valid; gchar *tstring; case G_TOKEN_EOF: g_snprintf (expected_string, expected_string_len, "end of file"); break; default: if (expected_token >= 1 && expected_token <= 255) { if ((expected_token >= ' ' && expected_token <= '~') || strchr (scanner->config->cset_identifier_first, expected_token) || strchr (scanner->config->cset_identifier_nth, expected_token)) g_snprintf (expected_string, expected_string_len, "character `%c'", expected_token); else g_snprintf (expected_string, expected_string_len, "character `\\%o'", expected_token); break; } else if (!scanner->config->symbol_2_token) { g_snprintf (expected_string, expected_string_len, "(unknown) token <%d>", expected_token); break; } /* fall through */ case G_TOKEN_SYMBOL: need_valid = (scanner->token == G_TOKEN_SYMBOL || (scanner->config->symbol_2_token && scanner->token > G_TOKEN_LAST)); g_snprintf (expected_string, expected_string_len, "%s%s", need_valid ? "valid " : "", symbol_spec); /* FIXME: should we attempt to lookup the symbol_name for symbol_2_token? */ break; case G_TOKEN_CHAR: g_snprintf (expected_string, expected_string_len, "%scharacter", scanner->token == G_TOKEN_CHAR ? "valid " : ""); break; case G_TOKEN_BINARY: tstring = "binary"; g_snprintf (expected_string, expected_string_len, "%snumber (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case G_TOKEN_OCTAL: tstring = "octal"; g_snprintf (expected_string, expected_string_len, "%snumber (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case G_TOKEN_INT: tstring = "integer"; g_snprintf (expected_string, expected_string_len, "%snumber (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case G_TOKEN_HEX: tstring = "hexadecimal"; g_snprintf (expected_string, expected_string_len, "%snumber (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case G_TOKEN_FLOAT: tstring = "float"; g_snprintf (expected_string, expected_string_len, "%snumber (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case G_TOKEN_STRING: g_snprintf (expected_string, expected_string_len, "%sstring constant", scanner->token == G_TOKEN_STRING ? "valid " : ""); break; case G_TOKEN_IDENTIFIER: case G_TOKEN_IDENTIFIER_NULL: need_valid = (scanner->token == G_TOKEN_IDENTIFIER_NULL || scanner->token == G_TOKEN_IDENTIFIER); g_snprintf (expected_string, expected_string_len, "%s%s", need_valid ? "valid " : "", identifier_spec); break; case G_TOKEN_COMMENT_SINGLE: tstring = "single-line"; g_snprintf (expected_string, expected_string_len, "%scomment (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case G_TOKEN_COMMENT_MULTI: tstring = "multi-line"; g_snprintf (expected_string, expected_string_len, "%scomment (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case G_TOKEN_NONE: case G_TOKEN_ERROR: /* this is handled upon printout */ break; } if (message && message[0] != 0) message_prefix = " - "; else { message_prefix = ""; message = ""; } if (expected_token == G_TOKEN_ERROR) { msg_handler (scanner, "failure around %s%s%s", token_string, message_prefix, message); } else if (expected_token == G_TOKEN_NONE) { if (print_unexp) msg_handler (scanner, "unexpected %s%s%s", token_string, message_prefix, message); else msg_handler (scanner, "%s%s%s", token_string, message_prefix, message); } else { if (print_unexp) msg_handler (scanner, "unexpected %s, expected %s%s%s", token_string, expected_string, message_prefix, message); else msg_handler (scanner, "%s, expected %s%s%s", token_string, expected_string, message_prefix, message); } g_free (token_string); g_free (expected_string);}static voidg_scanner_get_token_i (GScanner *scanner, GTokenType *token_p, GTokenValue *value_p, guint *line_p, guint *position_p){ do { g_scanner_free_value (token_p, value_p); g_scanner_get_token_ll (scanner, token_p, value_p, line_p, position_p); } while (((*token_p > 0 && *token_p < 256) && strchr (scanner->config->cset_skip_characters, *token_p)) || (*token_p == G_TOKEN_CHAR && strchr (scanner->config->cset_skip_characters, value_p->v_char)) || (*token_p == G_TOKEN_COMMENT_MULTI && scanner->config->skip_comment_multi) || (*token_p == G_TOKEN_COMMENT_SINGLE && scanner->config->skip_comment_single));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -