// Process a triple quoted string, the leading """ of which has been seen, but // not consumed static token_t* triple_string(lexer_t* lexer) { consume_chars(lexer, 3); // Leading """ while(true) { if(is_eof(lexer)) return literal_doesnt_terminate(lexer); char c = look(lexer); if((c == '\"') && (lookn(lexer, 2) == '\"') && (lookn(lexer, 3) == '\"')) { consume_chars(lexer, 3); // Triple strings can end with 3 or more "s. If there are more than 3 // the extra ones are part of the string contents while(look(lexer) == '\"') { append_to_token(lexer, '\"'); consume_chars(lexer, 1); } normalise_string(lexer); return make_token_with_text(lexer, TK_STRING); } consume_chars(lexer, 1); append_to_token(lexer, c); } }
// Process a block comment the leading / * for which has been seen, but not // consumed static token_t* nested_comment(lexer_t* lexer) { consume_chars(lexer, 2); // Leading / * size_t depth = 1; while(depth > 0) { if(lexer->len <= 1) { lex_error(lexer, "Nested comment doesn't terminate"); lexer->ptr += lexer->len; lexer->len = 0; return make_token(lexer, TK_LEX_ERROR); } if(look(lexer) == '*' && lookn(lexer, 2) == '/') { consume_chars(lexer, 2); depth--; } else if(look(lexer) == '/' && lookn(lexer, 2) == '*') { consume_chars(lexer, 2); depth++; } else { consume_chars(lexer, 1); } } lexer->newline = false; return NULL; }
// Process a line comment the leading // for which has been seen, but not // consumed static token_t* line_comment(lexer_t* lexer) { consume_chars(lexer, 2); // Leading // // We don't consume the terminating newline here, but it will be handled next // as whitespace while(!is_eof(lexer) && (look(lexer) != '\n')) consume_chars(lexer, 1); return NULL; }
R_API int r_core_yank_file_all (RCore *core, const char *input) { ut64 adv = 0; if (!input) return R_FALSE; adv = consume_chars (input, ' '); IFDBG eprintf ("Filename: %s\n", input+adv); return perform_mapped_file_yank (core, 0, -1, input+adv); }
// Read a hex or unicode escape sequence, for which the leading \x has been // consumed. // The length specified is the number of hex digits expected. // On success return the unicode value. // On error return minus the number of characters processed (including the \x) // and do not report an error. static int read_hex_escape(lexer_t* lexer, int length) { uint32_t value = 0; int text_len = 2; // start with "\x" for(int i = 0; i < length; i++) { char c = look(lexer); int digit = 0; if((c >= '0') && (c <= '9')) digit = c - '0'; else if((c >= 'a') && (c <= 'f')) digit = c + 10 - 'a'; else if((c >= 'A') && (c <= 'F')) digit = c + 10 - 'A'; else return -text_len; text_len++; consume_chars(lexer, 1); value = (value << 4) + digit; } return value; }
R_API int r_core_yank_file_all(RCore *core, const char *input) { ut64 adv = 0; if (!input) { return false; } adv = consume_chars (input, ' '); return perform_mapped_file_yank (core, 0, -1, input + adv); }
// Process a slash, which has been seen, but not consumed static token_t* slash(lexer_t* lexer) { if(lookn(lexer, 2) == '*') return nested_comment(lexer); if(lookn(lexer, 2) == '/') return line_comment(lexer); consume_chars(lexer, 1); return make_token(lexer, TK_DIVIDE); }
// Process a triple quoted string, the leading """ of which has been seen, but // not consumed static token_t* triple_string(lexer_t* lexer) { consume_chars(lexer, 3); // Leading """ while(true) { if(is_eof(lexer)) return literal_doesnt_terminate(lexer); char c = look(lexer); if((c == '\"') && (lookn(lexer, 2) == '\"') && (lookn(lexer, 3) == '\"')) { consume_chars(lexer, 3); normalise_string(lexer); return make_token_with_text(lexer, TK_STRING); } consume_chars(lexer, 1); append_to_token(lexer, c); } }
static int_fast32_t signed_integer(parser_context *context) { skip_ws(context); char *begin = (char *)context->input + context->cursor; char *end; errno = 0; int_fast32_t value = (int_fast32_t)strtol(begin, &end, 10); if(0 != errno || begin == end) { context->result.code = ERR_INVALID_NUMBER; return 0; } context->result.code = JSONPATH_SUCCESS; consume_chars(context, (size_t)(end - begin)); return value; }
static void name(parser_context *context, step *name_step) { enter_state(context, ST_NAME); size_t offset = context->cursor; while(offset < context->length) { if('.' == context->input[offset] || '[' == context->input[offset]) { break; } offset++; } while(isspace(context->input[offset - 1])) { offset--; } bool quoted = false; if('\'' == get_char(context) && '\'' == context->input[offset - 1]) { consume_char(context); offset--; quoted = true; } name_step->test.name.length = offset - context->cursor; if(0 == name_step->test.name.length) { context->result.code = ERR_EXPECTED_NAME_CHAR; return; } name_step->test.name.value = (uint8_t *)calloc(1, name_step->test.name.length); if(NULL == name_step->test.name.value) { context->result.code = ERR_PARSER_OUT_OF_MEMORY; return; } memcpy(name_step->test.name.value, context->input + context->cursor, name_step->test.name.length); consume_chars(context, name_step->test.name.length); if(quoted) { consume_char(context); } skip_ws(context); }
static uint_fast32_t integer(parser_context *context) { skip_ws(context); if('-' == get_char(context)) { context->result.code = ERR_EXPECTED_INTEGER; return 0; } char *begin = (char *)context->input + context->cursor; char *end; errno = 0; uint_fast32_t value = (uint_fast32_t)strtoul(begin, &end, 10); if(0 != errno || begin == end) { context->result.code = ERR_INVALID_NUMBER; return 0; } context->result.code = JSONPATH_SUCCESS; consume_chars(context, (size_t)(end - begin)); return value; }
static void node_type_test(parser_context *context) { enter_state(context, ST_NODE_TYPE_TEST); step *current = make_step(context->current_step_kind, TYPE_TEST); if(NULL == current) { context->result.code = ERR_PARSER_OUT_OF_MEMORY; return; } push_step(context, current); size_t offset = context->cursor; while(offset < context->length) { if('(' == context->input[offset]) { break; } offset++; } size_t length = offset - context->cursor; if(0 == length) { context->result.code = ERR_EXPECTED_NODE_TYPE_TEST; return; } int32_t kind = node_type_test_value(context, length); if(-1 == kind) { context->result.code = ERR_EXPECTED_NODE_TYPE_TEST; return; } current->test.type = (enum type_test_kind)kind; consume_chars(context, length); context->result.code = JSONPATH_SUCCESS; }
R_API int r_core_yank_file_ex (RCore *core, const char *input) { ut64 len = 0, adv = 0, addr = 0; int res = R_FALSE; if (!input) return res; // get the number of bytes to yank adv = consume_chars (input, ' '); len = r_num_math (core->num, input+adv); if (len == 0) { eprintf ("ERROR: Number of bytes read must be > 0\n"); return res; } // get the addr/offset from in the file we want to read adv += find_next_char (input+adv, ' '); if (adv == 0) { eprintf ("ERROR: Address must be specified\n"); return res; } adv++; IFDBG eprintf ("Handling the input: %s\n", input+adv); // XXX - bug, will fail if address needs to be computed and has spaces addr = r_num_math (core->num, input+adv); adv += find_next_char (input+adv, ' '); if (adv == 0) { eprintf ("ERROR: File must be specified\n"); return res; } adv++; IFDBG eprintf ("Filename: %s\n", input+adv); // grab the current file descriptor, so we can reset core and io state // after our io op is done return perform_mapped_file_yank (core, addr, len, input+adv); }
// Process a string or character escape sequence, the leading \ of which has // been seen but not consumed. // Errors are reported at the start of the sequence (ie the \ ). // Returns the escape value or <0 on error. static int escape(lexer_t* lexer, bool unicode_allowed) { // Record the start position of the escape sequence for error reporting const char* start = &lexer->source->m[lexer->ptr]; size_t line = lexer->line; size_t pos = lexer->pos; char c = lookn(lexer, 2); consume_chars(lexer, 2); int value = -2; // Default is 2 bad characters, \ and whatever follows it int hex_digits = 0; switch(c) { case 'a': value = 0x07; break; case 'b': value = 0x08; break; case 'e': value = 0x1B; break; case 'f': value = 0x0C; break; case 'n': value = 0x0A; break; case 'r': value = 0x0D; break; case 't': value = 0x09; break; case 'v': value = 0x0B; break; case '\"': value = 0x22; break; case '\'': value = 0x27; break; case '\\': value = 0x5C; break; case '0': value = 0x00; break; case 'x': hex_digits = 2; break; case 'u': if(unicode_allowed) hex_digits = 4; break; case 'U': if(unicode_allowed) hex_digits = 6; break; } if(hex_digits > 0) { value = read_hex_escape(lexer, hex_digits); if(value < 0) { lex_error_at(lexer, line, pos, "Invalid escape sequence \"%.*s\", %d hex digits required", -value, start, hex_digits); return -1; } if(value > 0x10FFFF) { lex_error_at(lexer, line, pos, "Escape sequence \"%8s\" exceeds unicode range (0x10FFFF)", start); return -1; } } if(value < 0) { lex_error_at(lexer, line, pos, "Invalid escape sequence \"%.*s\"", -value, start); return -1; } return value; }