static int is_unlimited_literal (const char *arg) { size_t len = sizeof ("unlimited") - 1; arg = skip_spaces_const (arg); return (strncmp (arg, "unlimited", len) == 0 && (isspace (arg[len]) || arg[len] == '\0')); }
int get_number_or_range (struct get_number_or_range_state *state) { if (*state->string != '-') { /* Default case: state->string is pointing either to a solo number, or to the first number of a range. */ state->last_retval = get_number_trailer (&state->string, '-'); if (*state->string == '-') { const char **temp; /* This is the start of a range (<number1> - <number2>). Skip the '-', parse and remember the second number, and also remember the end of the final token. */ temp = &state->end_ptr; state->end_ptr = skip_spaces_const (state->string + 1); state->end_value = get_number_const (temp); if (state->end_value < state->last_retval) { error (_("inverted range")); } else if (state->end_value == state->last_retval) { /* Degenerate range (number1 == number2). Advance the token pointer so that the range will be treated as a single number. */ state->string = state->end_ptr; } else state->in_range = 1; } } else if (! state->in_range) error (_("negative value")); else { /* state->string points to the '-' that betokens a range. All number-parsing has already been done. Return the next integer value (one greater than the saved previous value). Do not advance the token pointer until the end of range is reached. */ if (++state->last_retval == state->end_value) { /* End of range reached; advance token pointer. */ state->string = state->end_ptr; state->in_range = 0; } } state->finished = *state->string == '\0'; return state->last_retval; }
char * extract_arg_const (const char **arg) { const char *result; if (!*arg) return NULL; /* Find the start of the argument. */ *arg = skip_spaces_const (*arg); if (!**arg) return NULL; result = *arg; /* Find the end of the argument. */ *arg = skip_to_space_const (*arg + 1); if (result == *arg) return NULL; return savestring (result, *arg - result); }
event_location_up string_to_explicit_location (const char **argp, const struct language_defn *language, int dont_throw) { event_location_up location; /* It is assumed that input beginning with '-' and a non-digit character is an explicit location. "-p" is reserved, though, for probe locations. */ if (argp == NULL || *argp == NULL || *argp[0] != '-' || !isalpha ((*argp)[1]) || ((*argp)[0] == '-' && (*argp)[1] == 'p')) return NULL; location = new_explicit_location (NULL); /* Process option/argument pairs. dprintf_command requires that processing stop on ','. */ while ((*argp)[0] != '\0' && (*argp)[0] != ',') { int len; const char *start; /* If *ARGP starts with a keyword, stop processing options. */ if (linespec_lexer_lex_keyword (*argp) != NULL) break; /* Mark the start of the string in case we need to rewind. */ start = *argp; /* Get the option string. */ gdb::unique_xmalloc_ptr<char> opt = explicit_location_lex_one (argp, language); *argp = skip_spaces_const (*argp); /* Get the argument string. */ gdb::unique_xmalloc_ptr<char> oarg = explicit_location_lex_one (argp, language); bool have_oarg = oarg != NULL; *argp = skip_spaces_const (*argp); /* Use the length of the option to allow abbreviations. */ len = strlen (opt.get ()); /* All options have a required argument. Checking for this required argument is deferred until later. */ if (strncmp (opt.get (), "-source", len) == 0) EL_EXPLICIT (location)->source_filename = oarg.release (); else if (strncmp (opt.get (), "-function", len) == 0) EL_EXPLICIT (location)->function_name = oarg.release (); else if (strncmp (opt.get (), "-line", len) == 0) { if (have_oarg) EL_EXPLICIT (location)->line_offset = linespec_parse_line_offset (oarg.get ()); } else if (strncmp (opt.get (), "-label", len) == 0) EL_EXPLICIT (location)->label_name = oarg.release (); /* Only emit an "invalid argument" error for options that look like option strings. */ else if (opt.get ()[0] == '-' && !isdigit (opt.get ()[1])) { if (!dont_throw) error (_("invalid explicit location argument, \"%s\""), opt.get ()); } else { /* End of the explicit location specification. Stop parsing and return whatever explicit location was parsed. */ *argp = start; return location; } /* It's a little lame to error after the fact, but in this case, it provides a much better user experience to issue the "invalid argument" error before any missing argument error. */ if (!have_oarg && !dont_throw) error (_("missing argument for \"%s\""), opt.get ()); } /* One special error check: If a source filename was given without offset, function, or label, issue an error. */ if (EL_EXPLICIT (location)->source_filename != NULL && EL_EXPLICIT (location)->function_name == NULL && EL_EXPLICIT (location)->label_name == NULL && (EL_EXPLICIT (location)->line_offset.sign == LINE_OFFSET_UNKNOWN) && !dont_throw) { error (_("Source filename requires function, label, or " "line offset.")); } return location; }
static int aarch64_stap_parse_special_token (struct gdbarch *gdbarch, struct stap_parse_info *p) { if (*p->arg == '[') { /* Temporary holder for lookahead. */ const char *tmp = p->arg; char *endp; /* Used to save the register name. */ const char *start; char *regname; int len; int got_minus = 0; long displacement; struct stoken str; ++tmp; start = tmp; /* Register name. */ while (isalnum (*tmp)) ++tmp; if (*tmp != ',') return 0; len = tmp - start; regname = (char *) alloca (len + 2); strncpy (regname, start, len); regname[len] = '\0'; if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1) error (_("Invalid register name `%s' on expression `%s'."), regname, p->saved_arg); ++tmp; tmp = skip_spaces_const (tmp); /* Now we expect a number. It can begin with '#' or simply a digit. */ if (*tmp == '#') ++tmp; if (*tmp == '-') { ++tmp; got_minus = 1; } else if (*tmp == '+') ++tmp; if (!isdigit (*tmp)) return 0; displacement = strtol (tmp, &endp, 10); tmp = endp; /* Skipping last `]'. */ if (*tmp++ != ']') return 0; /* The displacement. */ write_exp_elt_opcode (&p->pstate, OP_LONG); write_exp_elt_type (&p->pstate, builtin_type (gdbarch)->builtin_long); write_exp_elt_longcst (&p->pstate, displacement); write_exp_elt_opcode (&p->pstate, OP_LONG); if (got_minus) write_exp_elt_opcode (&p->pstate, UNOP_NEG); /* The register name. */ write_exp_elt_opcode (&p->pstate, OP_REGISTER); str.ptr = regname; str.length = len; write_exp_string (&p->pstate, str); write_exp_elt_opcode (&p->pstate, OP_REGISTER); write_exp_elt_opcode (&p->pstate, BINOP_ADD); /* Casting to the expected type. */ write_exp_elt_opcode (&p->pstate, UNOP_CAST); write_exp_elt_type (&p->pstate, lookup_pointer_type (p->arg_type)); write_exp_elt_opcode (&p->pstate, UNOP_CAST); write_exp_elt_opcode (&p->pstate, UNOP_IND); p->arg = tmp; } else return 0; return 1; }
struct serial * serial_open (const char *name) { struct serial *scb; const struct serial_ops *ops; const char *open_name = name; if (strcmp (name, "pc") == 0) ops = serial_interface_lookup ("pc"); else if (startswith (name, "lpt")) ops = serial_interface_lookup ("parallel"); else if (startswith (name, "|")) { ops = serial_interface_lookup ("pipe"); /* Discard ``|'' and any space before the command itself. */ ++open_name; open_name = skip_spaces_const (open_name); } /* Check for a colon, suggesting an IP address/port pair. Do this *after* checking for all the interesting prefixes. We don't want to constrain the syntax of what can follow them. */ else if (strchr (name, ':')) ops = serial_interface_lookup ("tcp"); else ops = serial_interface_lookup ("hardwire"); if (!ops) return NULL; scb = XNEW (struct serial); scb->ops = ops; scb->bufcnt = 0; scb->bufp = scb->buf; scb->error_fd = -1; scb->refcnt = 1; /* `...->open (...)' would get expanded by the open(2) syscall macro. */ if ((*scb->ops->open) (scb, open_name)) { xfree (scb); return NULL; } scb->name = xstrdup (name); scb->next = scb_base; scb->debug_p = 0; scb->async_state = 0; scb->async_handler = NULL; scb->async_context = NULL; scb_base = scb; if (serial_logfile != NULL) { serial_logfp = gdb_fopen (serial_logfile, "w"); if (serial_logfp == NULL) perror_with_name (serial_logfile); } return scb; }
static int arm_stap_parse_special_token (struct gdbarch *gdbarch, struct stap_parse_info *p) { if (*p->arg == '[') { /* Temporary holder for lookahead. */ const char *tmp = p->arg; char *endp; /* Used to save the register name. */ const char *start; char *regname; int len, offset; int got_minus = 0; long displacement; struct stoken str; ++tmp; start = tmp; /* Register name. */ while (isalnum (*tmp)) ++tmp; if (*tmp != ',') return 0; len = tmp - start; regname = alloca (len + 2); offset = 0; if (isdigit (*start)) { /* If we are dealing with a register whose name begins with a digit, it means we should prefix the name with the letter `r', because GDB expects this name pattern. Otherwise (e.g., we are dealing with the register `fp'), we don't need to add such a prefix. */ regname[0] = 'r'; offset = 1; } strncpy (regname + offset, start, len); len += offset; regname[len] = '\0'; if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1) error (_("Invalid register name `%s' on expression `%s'."), regname, p->saved_arg); ++tmp; tmp = skip_spaces_const (tmp); if (*tmp++ != '#') return 0; if (*tmp == '-') { ++tmp; got_minus = 1; } displacement = strtol (tmp, &endp, 10); tmp = endp; /* Skipping last `]'. */ if (*tmp++ != ']') return 0; /* The displacement. */ write_exp_elt_opcode (OP_LONG); write_exp_elt_type (builtin_type (gdbarch)->builtin_long); write_exp_elt_longcst (displacement); write_exp_elt_opcode (OP_LONG); if (got_minus) write_exp_elt_opcode (UNOP_NEG); /* The register name. */ write_exp_elt_opcode (OP_REGISTER); str.ptr = regname; str.length = len; write_exp_string (str); write_exp_elt_opcode (OP_REGISTER); write_exp_elt_opcode (BINOP_ADD); /* Casting to the expected type. */ write_exp_elt_opcode (UNOP_CAST); write_exp_elt_type (lookup_pointer_type (p->arg_type)); write_exp_elt_opcode (UNOP_CAST); write_exp_elt_opcode (UNOP_IND); p->arg = tmp; } else return 0; return 1; }
int get_number_trailer (const char **pp, int trailer) { int retval = 0; /* default */ const char *p = *pp; if (*p == '$') { struct value *val = value_from_history_ref (p, &p); if (val) /* Value history reference */ { if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT) retval = value_as_long (val); else { printf_filtered (_("History value must have integer type.\n")); retval = 0; } } else /* Convenience variable */ { /* Internal variable. Make a copy of the name, so we can null-terminate it to pass to lookup_internalvar(). */ char *varname; const char *start = ++p; LONGEST val; while (isalnum (*p) || *p == '_') p++; varname = (char *) alloca (p - start + 1); strncpy (varname, start, p - start); varname[p - start] = '\0'; if (get_internalvar_integer (lookup_internalvar (varname), &val)) retval = (int) val; else { printf_filtered (_("Convenience variable must " "have integer value.\n")); retval = 0; } } } else { if (*p == '-') ++p; while (*p >= '0' && *p <= '9') ++p; if (p == *pp) /* There is no number here. (e.g. "cond a == b"). */ { /* Skip non-numeric token. */ while (*p && !isspace((int) *p)) ++p; /* Return zero, which caller must interpret as error. */ retval = 0; } else retval = atoi (*pp); } if (!(isspace (*p) || *p == '\0' || *p == trailer)) { /* Trailing junk: return 0 and let caller print error msg. */ while (!(isspace (*p) || *p == '\0' || *p == trailer)) ++p; retval = 0; } p = skip_spaces_const (p); *pp = p; return retval; }
static int get_tid_or_range (struct tid_range_parser *parser, int *inf_num, int *thr_start, int *thr_end) { if (parser->state == TID_RANGE_STATE_INFERIOR) { const char *p; const char *space; space = skip_to_space (parser->string); p = parser->string; while (p < space && *p != '.') p++; if (p < space) { const char *dot = p; /* Parse number to the left of the dot. */ p = parser->string; parser->inf_num = get_positive_number_trailer (&p, '.', parser->string); if (parser->inf_num == 0) return 0; parser->qualified = 1; p = dot + 1; if (isspace (*p)) return 0; } else { parser->inf_num = parser->default_inferior; parser->qualified = 0; p = parser->string; } init_number_or_range (&parser->range_parser, p); if (p[0] == '*' && (p[1] == '\0' || isspace (p[1]))) { /* Setup the number range parser to return numbers in the whole [1,INT_MAX] range. */ number_range_setup_range (&parser->range_parser, 1, INT_MAX, skip_spaces_const (p + 1)); parser->state = TID_RANGE_STATE_STAR_RANGE; } else parser->state = TID_RANGE_STATE_THREAD_RANGE; } *inf_num = parser->inf_num; *thr_start = get_number_or_range (&parser->range_parser); if (*thr_start < 0) error (_("negative value: %s"), parser->string); if (*thr_start == 0) { parser->state = TID_RANGE_STATE_INFERIOR; return 0; } /* If we successfully parsed a thread number or finished parsing a thread range, switch back to assuming the next TID is inferior-qualified. */ if (parser->range_parser.end_ptr == NULL || parser->range_parser.string == parser->range_parser.end_ptr) { parser->state = TID_RANGE_STATE_INFERIOR; parser->string = parser->range_parser.string; if (thr_end != NULL) *thr_end = *thr_start; } /* If we're midway through a range, and the caller wants the end value, return it and skip to the end of the range. */ if (thr_end != NULL && (parser->state == TID_RANGE_STATE_THREAD_RANGE || parser->state == TID_RANGE_STATE_STAR_RANGE)) { *thr_end = parser->range_parser.end_value; tid_range_parser_skip (parser); } return (*inf_num != 0 && *thr_start != 0); }
static void parse_find_args (char *args, ULONGEST *max_countp, gdb_byte **pattern_bufp, ULONGEST *pattern_lenp, CORE_ADDR *start_addrp, ULONGEST *search_space_lenp, bfd_boolean big_p) { /* Default to using the specified type. */ char size = '\0'; ULONGEST max_count = ~(ULONGEST) 0; /* Buffer to hold the search pattern. */ gdb_byte *pattern_buf; /* Current size of search pattern buffer. We realloc space as needed. */ #define INITIAL_PATTERN_BUF_SIZE 100 ULONGEST pattern_buf_size = INITIAL_PATTERN_BUF_SIZE; /* Pointer to one past the last in-use part of pattern_buf. */ gdb_byte *pattern_buf_end; ULONGEST pattern_len; CORE_ADDR start_addr; ULONGEST search_space_len; const char *s = args; struct cleanup *old_cleanups; struct value *v; if (args == NULL) error (_("Missing search parameters.")); pattern_buf = xmalloc (pattern_buf_size); pattern_buf_end = pattern_buf; old_cleanups = make_cleanup (free_current_contents, &pattern_buf); /* Get search granularity and/or max count if specified. They may be specified in either order, together or separately. */ while (*s == '/') { ++s; while (*s != '\0' && *s != '/' && !isspace (*s)) { if (isdigit (*s)) { max_count = atoi (s); while (isdigit (*s)) ++s; continue; } switch (*s) { case 'b': case 'h': case 'w': case 'g': size = *s++; break; default: error (_("Invalid size granularity.")); } } s = skip_spaces_const (s); } /* Get the search range. */ v = parse_to_comma_and_eval (&s); start_addr = value_as_address (v); if (*s == ',') ++s; s = skip_spaces_const (s); if (*s == '+') { LONGEST len; ++s; v = parse_to_comma_and_eval (&s); len = value_as_long (v); if (len == 0) { do_cleanups (old_cleanups); printf_filtered (_("Empty search range.\n")); return; } if (len < 0) error (_("Invalid length.")); /* Watch for overflows. */ if (len > CORE_ADDR_MAX || (start_addr + len - 1) < start_addr) error (_("Search space too large.")); search_space_len = len; } else { CORE_ADDR end_addr; v = parse_to_comma_and_eval (&s); end_addr = value_as_address (v); if (start_addr > end_addr) error (_("Invalid search space, end precedes start.")); search_space_len = end_addr - start_addr + 1; /* We don't support searching all of memory (i.e. start=0, end = 0xff..ff). Bail to avoid overflows later on. */ if (search_space_len == 0) error (_("Overflow in address range " "computation, choose smaller range.")); } if (*s == ',') ++s; /* Fetch the search string. */ while (*s != '\0') { LONGEST x; struct type *t; ULONGEST pattern_buf_size_need; s = skip_spaces_const (s); v = parse_to_comma_and_eval (&s); t = value_type (v); /* Keep it simple and assume size == 'g' when watching for when we need to grow the pattern buf. */ pattern_buf_size_need = (pattern_buf_end - pattern_buf + max (TYPE_LENGTH (t), sizeof (int64_t))); if (pattern_buf_size_need > pattern_buf_size) { size_t current_offset = pattern_buf_end - pattern_buf; pattern_buf_size = pattern_buf_size_need * 2; pattern_buf = xrealloc (pattern_buf, pattern_buf_size); pattern_buf_end = pattern_buf + current_offset; } if (size != '\0') { x = value_as_long (v); switch (size) { case 'b': *pattern_buf_end++ = x; break; case 'h': put_bits (x, pattern_buf_end, 16, big_p); pattern_buf_end += sizeof (int16_t); break; case 'w': put_bits (x, pattern_buf_end, 32, big_p); pattern_buf_end += sizeof (int32_t); break; case 'g': put_bits (x, pattern_buf_end, 64, big_p); pattern_buf_end += sizeof (int64_t); break; } } else { memcpy (pattern_buf_end, value_contents (v), TYPE_LENGTH (t)); pattern_buf_end += TYPE_LENGTH (t); } if (*s == ',') ++s; s = skip_spaces_const (s); } if (pattern_buf_end == pattern_buf) error (_("Missing search pattern.")); pattern_len = pattern_buf_end - pattern_buf; if (search_space_len < pattern_len) error (_("Search space too small to contain pattern.")); *max_countp = max_count; *pattern_bufp = pattern_buf; *pattern_lenp = pattern_len; *start_addrp = start_addr; *search_space_lenp = search_space_len; /* We successfully parsed the arguments, leave the freeing of PATTERN_BUF to the caller now. */ discard_cleanups (old_cleanups); }