📄 safescanner.c
字号:
SafeTokenValue 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;}guintsafe_scanner_cur_line (SafeScanner *scanner){ g_return_val_if_fail (scanner != NULL, 0); return scanner->line;}guintsafe_scanner_cur_position (SafeScanner *scanner){ g_return_val_if_fail (scanner != NULL, 0); return scanner->position;}gbooleansafe_scanner_eof (SafeScanner *scanner){ g_return_val_if_fail (scanner != NULL, TRUE); return scanner->token == SAFE_TOKEN_EOF || scanner->token == SAFE_TOKEN_ERROR;}voidsafe_scanner_input_file (SafeScanner *scanner, gint input_fd){ g_return_if_fail (scanner != NULL); g_return_if_fail (input_fd >= 0); if (scanner->input_fd >= 0) safe_scanner_sync_file_offset (scanner); scanner->token = SAFE_TOKEN_NONE; scanner->value.v_int = 0; scanner->line = 1; scanner->position = 0; scanner->next_token = SAFE_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);}voidsafe_scanner_input_text (SafeScanner *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) safe_scanner_sync_file_offset (scanner); scanner->token = SAFE_TOKEN_NONE; scanner->value.v_int = 0; scanner->line = 1; scanner->position = 0; scanner->next_token = SAFE_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 gucharsafe_scanner_peek_next_char (SafeScanner *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;}voidsafe_scanner_sync_file_offset (SafeScanner *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 gucharsafe_scanner_get_char (SafeScanner *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) { safe_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;}voidsafe_scanner_unexp_token (SafeScanner *scanner, SafeTokenType 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) (SafeScanner*, const gchar*, ...); g_return_if_fail (scanner != NULL); if (is_error) msg_handler = safe_scanner_error; else msg_handler = safe_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 SAFE_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 SAFE_TOKEN_SYMBOL: if (expected_token == SAFE_TOKEN_SYMBOL || (scanner->config->symbol_2_token && expected_token > SAFE_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 SAFE_TOKEN_ERROR: print_unexp = FALSE; expected_token = SAFE_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 SAFE_TOKEN_CHAR: g_snprintf (token_string, token_string_len, "character `%c'", scanner->value.v_char); break; case SAFE_TOKEN_IDENTIFIER: case SAFE_TOKEN_IDENTIFIER_NULL: if (expected_token == SAFE_TOKEN_IDENTIFIER || expected_token == SAFE_TOKEN_IDENTIFIER_NULL) print_unexp = FALSE; g_snprintf (token_string, token_string_len, "%s%s `%s'", print_unexp ? "" : "invalid ", identifier_spec, scanner->token == SAFE_TOKEN_IDENTIFIER ? scanner->value.v_string : "null"); break; case SAFE_TOKEN_BINARY: case SAFE_TOKEN_OCTAL: case SAFE_TOKEN_INT: case SAFE_TOKEN_HEX: g_snprintf (token_string, token_string_len, "number `%ld'", scanner->value.v_int); break; case SAFE_TOKEN_FLOAT: g_snprintf (token_string, token_string_len, "number `%.3f'", scanner->value.v_float); break; case SAFE_TOKEN_STRING: if (expected_token == SAFE_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 SAFE_TOKEN_COMMENT_SINGLE: case SAFE_TOKEN_COMMENT_MULTI: g_snprintf (token_string, token_string_len, "comment"); break; case SAFE_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 * safe_scanner_peek_next_token(); safe_scanner_unexp_token(); * without an intermediate safe_scanner_get_next_token(). */ g_assert_not_reached (); break; } switch (expected_token) { gboolean need_valid; gchar *tstring; case SAFE_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 SAFE_TOKEN_SYMBOL: need_valid = (scanner->token == SAFE_TOKEN_SYMBOL || (scanner->config->symbol_2_token && scanner->token > SAFE_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 SAFE_TOKEN_CHAR: g_snprintf (expected_string, expected_string_len, "%scharacter", scanner->token == SAFE_TOKEN_CHAR ? "valid " : ""); break; case SAFE_TOKEN_BINARY: tstring = "binary"; g_snprintf (expected_string, expected_string_len, "%snumber (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case SAFE_TOKEN_OCTAL: tstring = "octal"; g_snprintf (expected_string, expected_string_len, "%snumber (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case SAFE_TOKEN_INT: tstring = "integer"; g_snprintf (expected_string, expected_string_len, "%snumber (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case SAFE_TOKEN_HEX: tstring = "hexadecimal"; g_snprintf (expected_string, expected_string_len, "%snumber (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case SAFE_TOKEN_FLOAT: tstring = "float"; g_snprintf (expected_string, expected_string_len, "%snumber (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case SAFE_TOKEN_STRING: g_snprintf (expected_string, expected_string_len, "%sstring constant", scanner->token == SAFE_TOKEN_STRING ? "valid " : ""); break; case SAFE_TOKEN_IDENTIFIER: case SAFE_TOKEN_IDENTIFIER_NULL: need_valid = (scanner->token == SAFE_TOKEN_IDENTIFIER_NULL || scanner->token == SAFE_TOKEN_IDENTIFIER); g_snprintf (expected_string, expected_string_len, "%s%s", need_valid ? "valid " : "", identifier_spec); break; case SAFE_TOKEN_COMMENT_SINGLE: tstring = "single-line"; g_snprintf (expected_string, expected_string_len, "%scomment (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case SAFE_TOKEN_COMMENT_MULTI: tstring = "multi-line"; g_snprintf (expected_string, expected_string_len, "%scomment (%s)", scanner->token == expected_token ? "valid " : "", tstring); break; case SAFE_TOKEN_NONE: case SAFE_TOKEN_ERROR: /* this is handled upon printout */ break; } if (message && message[0] != 0) message_prefix = " - "; else { message_prefix = ""; message = ""; } if (expected_token == SAFE_TOKEN_ERROR) { msg_handler (scanner, "failure around %s%s%s", token_string, message_prefix, message); } else if (expected_token == SAFE_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 voidsafe_scanner_get_token_i (SafeScanner *scanner, SafeTokenType *token_p, SafeTokenValue *value_p, guint *line_p, guint *position_p){ do { safe_scanner_free_value (token_p, value_p); safe_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 == SAFE_TOKEN_CHAR && strchr (scanner->config->cset_skip_characters, value_p->v_char)) || (*token_p == SAFE_TOKEN_COMMENT_MULTI && scanner->config->skip_comment_multi) || (*token_p == SAFE_TOKEN_COMMENT_SINGLE && scanner->config->skip_comment_single)); switch (*token_p) { case SAFE_TOKEN_IDENTIFIER: if (scanner->config->identifier_2_string) *token_p = SAFE_TOKEN_STRING; break; case SAFE_TOKEN_SYMBOL: if (scanner->config->symbol_2_token) *token_p = (SafeTokenType) value_p->v_symbol; break; case SAFE_TOKEN_BINARY: case SAFE_TOKEN_OCTAL: case SAFE_TOKEN_HEX: if (scanner->config->numbers_2_int) *token_p = SAFE_TOKEN_INT; break; default: break; } if (*token_p == SAFE_TOKEN_INT && scanner->config->int_2_float) { *token_p = SAFE_TOKEN_FLOAT; value_p->v_float = value_p->v_int; } errno = 0;}static voidsafe_scanner_get_token_ll (SafeScanner *scanner, SafeTokenType *token_p, SafeTokenValue *value_p, guint *line_p, guint *position_p){ SafeScannerConfig *config; SafeTokenType token; gboolean in_comment_multi; gboolean in_comment_single; gboolean in_string_sq; gboolean in_string_dq; GString *gstring; SafeTokenValue value; guchar ch; gboolean i_saw_escape_char;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -