This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA 3/5] Explicit linespecs - implementation


On Fri, 27 Jul 2012 05:47:56 +0200, Keith Seitz wrote:
> Questions/comments/concerns?

This adds yet another way how to specify linespecs.  Have you considered
removing the b->addr_string field completely?  What are the reasons for
conditional, thread, task not being already parsed into struct
explicit_linespec?  For example probes could also be in explicit_linespec.

I would see explicit_linespec as enum + union.  "expression" would be already
one enum type, classical linespec other type, probe yet another type, maybe
some more.

This way explicit_linespec would be always non-NULL and addr_string would be no
longer passed along.  Currently all the use of both explicit_linespec and
addr_string together seem error prone to me.


Thanks,
Jan


> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index 35d55ba..1058a35 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -3486,7 +3486,7 @@ update_breakpoints_after_exec (void)
>      /* Without a symbolic address, we have little hope of the
>         pre-exec() address meaning the same thing in the post-exec()
>         a.out.  */
> -    if (b->addr_string == NULL)
> +    if (b->addr_string == NULL && b->explicit == NULL)
>        {
>  	delete_breakpoint (b);
>  	continue;
> @@ -5688,7 +5688,19 @@ print_breakpoint_location (struct breakpoint *b,
>        do_cleanups (stb_chain);
>      }
>    else
> -    ui_out_field_string (uiout, "pending", b->addr_string);
> +    {
> +      char *where = b->addr_string;

const char *

> +      struct cleanup *free_where = make_cleanup (null_cleanup, NULL);
> +
> +      if (b->explicit != NULL)
> +	{
> +	  where = explicit_linespec_to_string (b->explicit, b->addr_string);
> +	  make_cleanup (xfree, where);

Here you will need to use a different variable.

In fact it would be easier then to just call ui_out_field_string two times.

> +	}
> +
> +      ui_out_field_string (uiout, "pending", where);
> +      do_cleanups (free_where);
> +    }
>  
>    if (loc && is_breakpoint (b)
>        && breakpoint_condition_evaluation_mode () == condition_evaluation_target
> @@ -5757,6 +5769,14 @@ bptype_string (enum bptype type)
>    return bptypes[(int) type].description;
>  }
>  
> +/* Throw an exception for unsupported explicit linespec.  */
> +
> +static void ATTRIBUTE_NORETURN
> +explicit_linespec_unsupported (enum bptype type)
> +{
> +  error (_("explicit linespec not supported for %s"), bptype_string (type));

Error should be a sentence, capital 'E', "is not".


> +}
> +
>  /* Print B to gdb_stdout.  */
>  
>  static void
> @@ -9009,6 +9029,8 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
>         me.  */
>      b->addr_string
>        = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
> +  if (els != NULL)
> +    b->explicit = copy_explicit_linespec (els);
>    b->filter = filter;
>  }
>  
> @@ -9040,7 +9062,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
>    old_chain = make_cleanup (xfree, b);
>  
>    init_breakpoint_sal (b, gdbarch,
> -		       sals, NULL, addr_string,
> +		       sals, els, addr_string,
>  		       filter, cond_string, extra_string,
>  		       type, disposition,
>  		       thread, task, ignore_count,
> @@ -9094,7 +9116,7 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
>  
>        make_cleanup (xfree, filter_string);
>        create_breakpoint_sal (gdbarch, lsal->sals,
> -			     NULL, addr_string,
> +			     canonical->explicit, addr_string,
>  			     filter_string,
>  			     cond_string, extra_string,
>  			     type, disposition,
> @@ -9121,8 +9143,9 @@ parse_breakpoint_sals (explicit_linespec *els, char **address,
>  
>    /* If no arg given, or if first arg is 'if ', use the default
>       breakpoint.  */
> -  if ((*address) == NULL
> -      || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2])))
> +  if (els == NULL
> +      && ((*address) == NULL
> +	  || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))))
>      {
>        /* The last displayed codepoint, if it's valid, is our default breakpoint
>           address.  */
> @@ -9167,17 +9190,33 @@ parse_breakpoint_sals (explicit_linespec *els, char **address,
>  
>  	 ObjC: However, don't match an Objective-C method name which
>  	 may have a '+' or '-' succeeded by a '['.  */
> -      if (last_displayed_sal_is_valid ()
> -	  && (!cursal.symtab
> -	      || ((strchr ("+-", (*address)[0]) != NULL)
> -		  && ((*address)[1] != '['))))
> -	decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
> -			  get_last_displayed_symtab (),
> -			  get_last_displayed_line (),
> -			  canonical, NULL, NULL);
> +      if (els != NULL)
> +	{
> +	  if (last_displayed_sal_is_valid ())
> +	    decode_explicit_linespec (els, DECODE_LINE_FUNFIRSTLINE,
> +                                      get_last_displayed_symtab (),
> +                                      get_last_displayed_line (),
> +                                      canonical, NULL, NULL);
> +	  else
> +	    decode_explicit_linespec (els, DECODE_LINE_FUNFIRSTLINE,
> +                                      NULL, 0, canonical,
> +                                      NULL, NULL);
> +	}
>        else
> -	decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
> -			  cursal.symtab, cursal.line, canonical, NULL, NULL);
> +	{
> +	  if (last_displayed_sal_is_valid ()
> +	      && (!cursal.symtab
> +		  || ((strchr ("+-", (*address)[0]) != NULL)
> +		      && ((*address)[1] != '['))))
> +	    decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
> +			      get_last_displayed_symtab (),
> +			      get_last_displayed_line (),
> +			      canonical, NULL, NULL);
> +	  else
> +	    decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
> +                              cursal.symtab, cursal.line, canonical,
> +                              NULL, NULL);
> +	}
>      }
>  }
>  
> @@ -9536,6 +9575,8 @@ create_breakpoint_1 (struct gdbarch *gdbarch,
>  
>        init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops);
>  
> +      if (canonical->explicit != NULL)
> +	b->explicit = copy_explicit_linespec (canonical->explicit);
>        if (canonical->addr_string)
>  	b->addr_string = xstrdup (canonical->addr_string);
>        if (parse_condition_and_thread)
> @@ -9636,10 +9677,12 @@ create_breakpoint (struct gdbarch *gdbarch, explicit_linespec *els,
>  
>    back_to = make_cleanup_destroy_linespec_result (&canonical);
>  
> -  if (canonical.addr_string == NULL)
> +  if (canonical.explicit == NULL)
>      {
>        if (addr_start)
>  	canonical.addr_string = xstrdup (addr_start);

I do not understand it much, using ADDR_START without ELS no longer makes
sense?  Parameter ELS of create_breakpoint is undocumented.


> +      if (els != NULL)
> +	canonical.explicit = copy_explicit_linespec (els);
>      }
>  
>    result = create_breakpoint_1 (gdbarch, &canonical, arg, cond_string,
> @@ -9666,7 +9709,9 @@ break_command_1 (char *arg, int flag, int from_tty)
>    enum bptype type_wanted = (flag & BP_HARDWAREFLAG
>  			     ? bp_hardware_breakpoint
>  			     : bp_breakpoint);
> +  explicit_linespec *els;
>    struct breakpoint_ops *ops;
> +  struct cleanup *back_to;
>    const char *arg_cp = arg;
>  
>    /* Matching breakpoints on probes.  */
> @@ -9675,8 +9720,11 @@ break_command_1 (char *arg, int flag, int from_tty)
>    else
>      ops = &bkpt_breakpoint_ops;
>  
> +  /* Check for an explicit linespec.  */
> +  els = string_to_explicit_linespec (&arg);
> +  back_to = make_cleanup (free_explicit_linespec, els);
>    create_breakpoint (get_current_arch (),
> -		     NULL, arg,
> +		     els, arg,
>  		     NULL, 0, NULL, 1 /* parse arg */,
>  		     tempflag, type_wanted,
>  		     0 /* Ignore count */,
> @@ -9686,6 +9734,7 @@ break_command_1 (char *arg, int flag, int from_tty)
>  		     1 /* enabled */,
>  		     0 /* internal */,
>  		     0);
> +  do_cleanups (back_to);
>  }
>  
>  /* Helper function for break_command_1 and disassemble_command.  */
> @@ -12639,7 +12688,17 @@ say_where (struct breakpoint *b)
>       single string.  */
>    if (b->loc == NULL)
>      {
> -      printf_filtered (_(" (%s) pending."), b->addr_string);
> +      char *where = b->addr_string;
> +      struct cleanup *free_where = make_cleanup (null_cleanup, NULL);
> +
> +      if (b->explicit != NULL)
> +	{
> +	  where = explicit_linespec_to_string (b->explicit, b->addr_string);
> +	  make_cleanup (xfree, where);
> +	}

Similar const vs. non-const comment like above.

> +
> +      printf_filtered (_(" (%s) pending."), where);
> +      do_cleanups (free_where);
>      }
>    else
>      {
> @@ -12702,6 +12761,7 @@ base_breakpoint_dtor (struct breakpoint *self)
>    xfree (self->addr_string);
>    xfree (self->filter);
>    xfree (self->addr_string_range_end);
> +  free_explicit_linespec (self->explicit);
>  }
>  
>  static struct bp_location *
> @@ -12854,7 +12914,7 @@ static void
>  bkpt_re_set (struct breakpoint *b)
>  {
>    /* FIXME: is this still reachable?  */
> -  if (b->addr_string == NULL)
> +  if (b->addr_string == NULL && b->explicit == NULL)
>      {
>        /* Anything without a string can't be re-set.  */
>        delete_breakpoint (b);
> @@ -13237,6 +13297,9 @@ bkpt_probe_create_sals_from_address (explicit_linespec *els, char **arg,
>  {
>    struct linespec_sals lsal;
>  
> +  if (els != NULL)
> +    explicit_linespec_unsupported (type_wanted);
> +
>    lsal.sals = parse_probes (arg, canonical);
>  
>    *copy_arg = xstrdup (canonical->addr_string);
> @@ -13249,6 +13312,9 @@ static void
>  bkpt_probe_decode_linespec (struct breakpoint *b, explicit_linespec *els,
>  			    char **s, struct symtabs_and_lines *sals)
>  {
> +  if (els != NULL)
> +    explicit_linespec_unsupported (b->type);
> +
>    *sals = parse_probes (s, NULL);
>    if (!sals->sals)
>      error (_("probe not found"));
> @@ -13461,7 +13527,7 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
>  
>        tp = XCNEW (struct tracepoint);
>        init_breakpoint_sal (&tp->base, gdbarch, expanded,
> -			   NULL, addr_string, NULL,
> +			   canonical->explicit, addr_string, NULL,
>  			   cond_string, extra_string,
>  			   type_wanted, disposition,
>  			   thread, task, ignore_count, ops,
> @@ -13487,6 +13553,9 @@ strace_marker_decode_linespec (struct breakpoint *b, explicit_linespec *els,
>  {
>    struct tracepoint *tp = (struct tracepoint *) b;
>  
> +  if (els != NULL)
> +    explicit_linespec_unsupported (b->type);
> +
>    *sals = decode_static_tracepoint_spec (s);
>    if (sals->nelts > tp->static_trace_marker_id_idx)
>      {
> @@ -14127,7 +14196,7 @@ breakpoint_re_set_default (struct breakpoint *b)
>    struct symtabs_and_lines expanded = {0};
>    struct symtabs_and_lines expanded_end = {0};
>  
> -  sals = addr_string_to_sals (b, NULL, b->addr_string, &found);
> +  sals = addr_string_to_sals (b, b->explicit, b->addr_string, &found);
>  
>    if (found)
>      {
> @@ -14137,7 +14206,7 @@ breakpoint_re_set_default (struct breakpoint *b)
>  
>    if (b->addr_string_range_end)
>      {
> -      sals_end = addr_string_to_sals (b, NULL, b->addr_string_range_end,
> +      sals_end = addr_string_to_sals (b, b->explicit, b->addr_string_range_end,
>  				      &found);
>        if (found)
>  	{
> @@ -14196,10 +14265,15 @@ decode_linespec_default (struct breakpoint *b, explicit_linespec *els,
>    struct linespec_result canonical;
>  
>    init_linespec_result (&canonical);
> -  decode_line_full (s, DECODE_LINE_FUNFIRSTLINE,
> -		    (struct symtab *) NULL, 0,
> -		    &canonical, multiple_symbols_all,
> -		    b->filter);
> +  if (els == NULL)
> +    decode_line_full (s, DECODE_LINE_FUNFIRSTLINE,
> +		      (struct symtab *) NULL, 0,

Just drop the cast (struct symtab *) (yes, it is just code move).


> +		      &canonical, multiple_symbols_all,
> +		      b->filter);
> +  else
> +    decode_explicit_linespec (els, DECODE_LINE_FUNFIRSTLINE,
> +			      NULL, 0, &canonical, multiple_symbols_all,
> +			      b->filter);
>  
>    /* We should get 0 or 1 resulting SALs.  */
>    gdb_assert (VEC_length (linespec_sals, canonical.sals) < 2);
> diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
> index 43be84a..3212f4f 100644
> --- a/gdb/breakpoint.h
> +++ b/gdb/breakpoint.h
> @@ -683,6 +683,11 @@ struct breakpoint
>      /* String we used to set the breakpoint (malloc'd).  */
>      char *addr_string;
>  
> +    /* The explicit linespec used to set the breakpoint (malloc'd).
> +       This may be computed by decode_line_full/decode_explicit_linespec
> +       or set by the user.  */

It can be sometimes NULL.  When?  [maybe obsolete comment now after the top
discussion]


> +    struct explicit_linespec *explicit;
> +
>      /* The filter that should be passed to decode_line_full when
>         re-setting this breakpoint.  This may be NULL, but otherwise is
>         allocated with xmalloc.  */
> diff --git a/gdb/linespec.c b/gdb/linespec.c
> index 2b84515..fcbf3dd 100644
> --- a/gdb/linespec.c
> +++ b/gdb/linespec.c
> @@ -1664,9 +1664,14 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
>    if (!state->canonical)
>      return;
>  
> +  state->canonical->explicit = new_explicit_linespec ();
> +
>    /* Shortcut expressions, which can only appear by themselves.  */
>    if (ls->expression != NULL)
> -    state->canonical->addr_string = xstrdup (ls->expression);
> +    {
> +      state->canonical->addr_string = xstrdup (ls->expression);
> +      state->canonical->explicit->expression = xstrdup (ls->expression);
> +    }
>    else
>      {
>        struct ui_file *buf;
> @@ -1676,6 +1681,8 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
>        if (ls->source_filename)
>  	{
>  	  fputs_unfiltered (ls->source_filename, buf);
> +	  state->canonical->explicit->source_filename
> +	    = xstrdup (ls->source_filename);
>  	  need_colon = 1;
>  	}
>  
> @@ -1684,6 +1691,8 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
>  	  if (need_colon)
>  	    fputc_unfiltered (':', buf);
>  	  fputs_unfiltered (ls->function_name, buf);
> +	  state->canonical->explicit->function_name
> +	    = xstrdup (ls->function_name);
>  	  need_colon = 1;
>  	}
>  
> @@ -1706,6 +1715,7 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
>  	    }
>  
>  	  fputs_unfiltered (ls->label_name, buf);
> +	  state->canonical->explicit->label_name = xstrdup (ls->label_name);
>  	  need_colon = 1;
>  	  state->canonical->special_display = 1;
>  	}
> @@ -1714,11 +1724,13 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
>  	{
>  	  if (need_colon)
>  	    fputc_unfiltered (':', buf);
> -	  fprintf_filtered (buf, "%s%d",
> -			    (ls->line_offset.sign == LINE_OFFSET_NONE ? ""
> -			     : (ls->line_offset.sign
> -				== LINE_OFFSET_PLUS ? "+" : "-")),
> -			    ls->line_offset.offset);
> +	  state->canonical->explicit->offset
> +	    = xstrprintf ("%s%d",
> +			  (ls->line_offset.sign == LINE_OFFSET_NONE ? ""
> +			   : (ls->line_offset.sign
> +			      == LINE_OFFSET_PLUS ? "+" : "-")),
> +			  ls->line_offset.offset);
> +	  fputs_filtered (state->canonical->explicit->offset, buf);
>  	}
>  
>        state->canonical->addr_string = ui_file_xstrdup (buf, NULL);
> @@ -2385,6 +2397,125 @@ decode_line_full (char **argptr, int flags,
>    do_cleanups (cleanups);
>  }
>  
> +/* A parsing function for explicit linespecs.  */
> +
> +static struct symtabs_and_lines
> +parse_explicit_linespec (linespec_parser *parser, void *data)
> +{
> +  VEC (symbolp) *symbols, *labels;
> +  VEC (minsym_and_objfile_d) *minimal_symbols;

It is only a style but I would prefer moving them into their blocks where they
are used (even if they will have to be declared multiple times).


> +  explicit_linespec *els = (explicit_linespec *) data;
> +
> +  if (els->expression != NULL)
> +    {
> +      char *copy = xstrdup (els->expression);
> +      struct cleanup *cleanup = make_cleanup (xfree, copy);
> +
> +      /* Convert the expression to a PC and save the result.  */
> +      PARSER_RESULT (parser)->expr_pc = linespec_expression_to_pc (&copy);
> +      PARSER_RESULT (parser)->expression = xstrdup (els->expression);
> +      do_cleanups (cleanup);
> +    }
> +  else
> +    {
> +      if (els->source_filename != NULL)
> +	{
> +	  volatile struct gdb_exception except;
> +
> +	  TRY_CATCH (except, RETURN_MASK_ERROR)
> +	    {
> +	      PARSER_RESULT (parser)->file_symtabs
> +		= symtabs_from_filename (els->source_filename);
> +	    }
> +
> +	  if (except.reason < 0
> +	      || PARSER_RESULT (parser)->file_symtabs == NULL)
> +	    source_file_not_found_error (els->source_filename);
> +
> +	  /* Save the source filename in the parser's result.  */
> +	  PARSER_RESULT (parser)->source_filename
> +	    = xstrdup (els->source_filename);
> +	}
> +      else
> +	{
> +	  /* A NULL entry means to use the default symtab.  */
> +	  VEC_safe_push (symtab_p, PARSER_RESULT (parser)->file_symtabs, NULL);
> +	}
> +
> +      if (els->function_name != NULL)
> +	{
> +	  find_linespec_symbols (PARSER_STATE (parser),
> +				 PARSER_RESULT (parser)->file_symtabs,
> +				 els->function_name, &symbols,
> +				 &minimal_symbols);
> +
> +	  if (symbols == NULL && minimal_symbols == NULL)
> +	    symbol_not_found_error (els->function_name,
> +				    PARSER_RESULT (parser)->source_filename);
> +
> +	  PARSER_RESULT (parser)->function_name = xstrdup (els->function_name);
> +	  PARSER_RESULT (parser)->function_symbols = symbols;
> +	  PARSER_RESULT (parser)->minimal_symbols = minimal_symbols;
> +	}
> +
> +      if (els->label_name != NULL)
> +	{
> +	  symbols = NULL;
> +	  labels = find_label_symbols (PARSER_STATE (parser),
> +				       PARSER_RESULT (parser)->function_symbols,
> +				       &symbols, els->label_name);
> +
> +	  if (labels == NULL)
> +	    undefined_label_error (PARSER_RESULT (parser)->function_name,
> +				   els->label_name);
> +
> +	  PARSER_RESULT (parser)->label_name = xstrdup (els->label_name);
> +	  PARSER_RESULT (parser)->labels.label_symbols = labels;
> +	  PARSER_RESULT (parser)->labels.function_symbols = symbols;
> +	}
> +
> +      if (els->offset != NULL)
> +	PARSER_RESULT (parser)->line_offset
> +	  = linespec_parse_line_offset (els->offset);
> +
> +      /* One special error check: If SOURCE_FILENAME was given without
> +	 OFFSET, FUNCTION_NAME, or LABEL_NAME, issue an error.  */
> +      if (PARSER_RESULT (parser)->source_filename != NULL
> +	  && PARSER_RESULT (parser)->function_name == NULL
> +	  && PARSER_RESULT (parser)->label_name == NULL
> +	  && PARSER_RESULT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN)
> +	error (_("Source filename requires function, label, or offset."));
> +    }
> +
> +  /* Convert the "parse" to SALs.  */
> +  return convert_linespec_to_sals (PARSER_STATE (parser),
> +				   PARSER_RESULT (parser));
> +}
> +
> +/* Decode the explicit linespec in ELS.  The other parameters are
> +   the same as decode_line_full.  */
> +
> +void
> +decode_explicit_linespec (explicit_linespec *els, int flags,
> +			  struct symtab *default_symtab,
> +			  int default_line, struct linespec_result *canonical,
> +			  const char *select_mode,
> +			  const char *filter)
> +{
> +  linespec_parser parser;
> +  struct cleanup *cleanups;
> +
> +  gdb_assert (canonical != NULL);
> +  gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0);
> +
> +  linespec_parser_new (&parser, parse_explicit_linespec, flags,
> +		       current_language, default_symtab,
> +		       default_line, canonical);
> +  cleanups = make_cleanup (linespec_parser_delete, &parser);
> +  do_decode_line (&parser, els, select_mode, filter);
> +  do_cleanups (cleanups);
> +}
> +
>  /* See linespec.h.  */
>  
>  struct symtabs_and_lines
> @@ -2487,7 +2618,8 @@ linespec_expression_to_pc (char **exp_ptr)
>      throw_error (NOT_FOUND_ERROR, _("cannot evaluate expressions while "
>  				    "program space is in startup"));
>  
> -  (*exp_ptr)++;
> +  if (**exp_ptr == '*')
> +    (*exp_ptr)++;

This is not right:

(gdb) l 1
1	int main (void) { return 0; }
2	int (*a) (void) = main;
3	int (**b) (void) = &a;
(gdb) p a
$1 = (int (*)(void)) 0x4004ec <main>
(gdb) p b
$2 = (int (**)(void)) 0x601018 <a>
(gdb) break -address b
Breakpoint 1 at 0x601018
(gdb) break -address *b
Note: breakpoint 1 also set at pc 0x601018.
Breakpoint 2 at 0x601018
(gdb) break -address (*b)
Breakpoint 3 at 0x4004ec: file 12.c, line 1.
(gdb) 

'*b' and '(*b)' should behave the same, they are not.


>    return value_as_address (parse_to_comma_and_eval (exp_ptr));
>  }
>  
> @@ -3573,6 +3705,7 @@ destroy_linespec_result (struct linespec_result *ls)
>    struct linespec_sals *lsal;
>  
>    xfree (ls->addr_string);
> +  free_explicit_linespec (ls->explicit);
>    for (i = 0; VEC_iterate (linespec_sals, ls->sals, i, lsal); ++i)
>      {
>        xfree (lsal->canonical);
> @@ -3596,3 +3729,299 @@ make_cleanup_destroy_linespec_result (struct linespec_result *ls)
>  {
>    return make_cleanup (cleanup_linespec_result, ls);
>  }
> +
> +/* Allocate and initialize a new explicit_linespec.  */
> +
> +explicit_linespec *
> +new_explicit_linespec (void)
> +{
> +  return XCNEW (explicit_linespec);
> +}
> +
> +/* Free the explicit_linespec represented by OBJ.  */
> +
> +void
> +free_explicit_linespec (void *obj)
> +{
> +  explicit_linespec *els = (explicit_linespec *) obj;
> +
> +  if (els != NULL)
> +    {
> +      xfree ((char *) els->source_filename);
> +      xfree ((char *) els->function_name);
> +      xfree ((char *) els->label_name);
> +      xfree ((char *) els->offset);
> +      xfree ((char *) els->expression);
> +      xfree (els);
> +    }
> +}
> +
> +/* A lexer for explicit linespecs. This function will advance INP past
> +   any strings that it returns.  Returns a malloc'd copy of the
> +   lexed string or NULL if no lexing was done.  */
> +
> +static char *
> +explicit_lex_one (char **inp)

Function does not modify the string itself, so it should be 'const char **'.


> +{
> +  char *start = *inp;
> +
> +  if (*start != '\0')

IMO rather return if (*start == '\0'), the function is needlessly indented
right now.


> +    {
> +      int lexing_number = 0;
> +
> +      /* If quoted, skip to the ending quote.  */
> +      if (strchr (linespec_quote_characters, *start))
> +	{
> +	  char quote_char = *start;
> +
> +	  /* If the input is not an ada operator, skip to the matching
> +	     closing quote and return the string.  */
> +	  if (!(current_language->la_language == language_ada
> +		&& quote_char == '\"' && is_ada_operator (start)))
> +	    {
> +	      const char *end = skip_quote_char (start + 1, quote_char);
> +
> +	      if (end == NULL)
> +		error (_("unmatched quote"));

It could print:
		error (_("unmatched quote starting at: %s"), start);

> +	      *inp = (char *) end + 1;
> +	      return savestring (start + 1, *inp - start - 2);
> +	    }
> +	}
> +
> +      /* Are we lexing a number?  */
> +      if ((start[0] == '-' || start[0] == '+')
> +	  && start[1] && isdigit (start[1]))
> +	{
> +	  /* The input is a relative offset.  */
> +	  lexing_number = 1;
> +
> +	  /* Skip the +/-.  */
> +	  ++(*inp);
> +	}
> +      else if (isdigit (*start))
> +	lexing_number = 1;
> +
> +      /* If the input starts with '-', the string ends with the next
> +	 whitespace.  */
> +      if (*start == '-')
> +	{
> +	  while ((*inp)[0] && !isspace ((*inp)[0]))
> +	    ++(*inp);
> +	}
> +      /* If lexing a number, stop at the first non-digit character.  */
> +      else if (lexing_number)
> +	{
> +	  while ((*inp)[0] && isdigit ((*inp)[0]))
> +	    ++(*inp);
> +	}
> +      else
> +	{
> +	  /* Otherwise, stop at the next occurrence of "SPACE -", '\0', or
> +	     keyword.  */
> +	  while ((*inp)[0]
> +		 && !(isspace ((*inp)[0])
> +		      && ((*inp)[1] == '-'
> +			  || linespec_lexer_lex_keyword (&(*inp)[1]))))
> +	    ++(*inp);
> +	}
> +    }
> +
> +  if (*inp - start > 0)
> +    return savestring (start, *inp - start);
> +
> +  return NULL;
> +}
> +
> +/* Attempt to convert the address string in *ARGP into an explicit_linespec.
> +   Returns the explicit linespec (which must be free'd by the caller) and
> +   advances ARGP over all processed input. Returns NULL if *ARGP does
> +   not describe an explicit linespec.
> +
> +   This function may call error() if the *ARGP looks like properly formed
> +   input, e.g., if it is called with missing argument parameters or
> +   invalid options.  */
> +
> +explicit_linespec *
> +string_to_explicit_linespec (char **argp)
> +{
> +

Excessive empty line.

> +  /* It is assumed that linespecs beginning with '-' and a non-digit
> +     character is an explicit linespec.  */
> +  if (argp != NULL && *argp != NULL)
> +    {
> +      const char *copy = *argp;
> +
> +      if (probe_linespec_to_ops (&copy) != NULL)
> +	{
> +	  /* Explicit linespecs with probes is not supported.  */
> +	  return NULL;
> +	}
> +
> +      if ((*argp)[0] == '-' && isalpha ((*argp)[1]))
> +	{
> +	  explicit_linespec *els;
> +	  struct cleanup *cleanup;
> +
> +	  els = new_explicit_linespec ();
> +	  cleanup = make_cleanup (free_explicit_linespec, els);
> +
> +	  /* Process option/argument pairs.  */
> +	  while ((*argp)[0] != '\0')
> +	    {
> +	      int len;
> +	      char *opt, *oarg, *start;
> +	      struct cleanup *inner;
> +
> +	      /* 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.  */
> +	      opt = explicit_lex_one (argp);
> +	      inner = make_cleanup (xfree, opt);
> +
> +	      /* Skip any whitespace.  */
> +	      *argp = skip_spaces (*argp);
> +
> +	      /* Get the argument string.  */
> +	      oarg = explicit_lex_one (argp);
> +	      make_cleanup (xfree, oarg);
> +
> +	      /* Skip any whitespace.  */
> +	      *argp = skip_spaces (*argp);
> +
> +	      /* Use the length of the option to allow abbreviations.  */
> +	      len = strlen (opt);
> +
> +	      /* All options have a required argument.  */
> +	      if (strncmp (opt, "-source", len) == 0)
> +		els->source_filename = oarg;
> +	      else if (strncmp (opt, "-function", len) == 0)
> +		els->function_name = oarg;
> +	      else if (strncmp (opt, "-label", len) == 0)
> +		els->label_name = oarg;
> +	      else if (strncmp (opt, "-offset", len) == 0)
> +		els->offset = oarg;
> +	      else if (strncmp (opt, "-address", len) == 0)
> +		els->expression = oarg;

I do not see these options documented in "help break".


> +	      /* Only emit an "invalid argument" error for options
> +		 that look like option strings.  */
> +	      else if (opt[0] == '-' && !isdigit (opt[1]))
> +		error (_("invalid linespec argument, \"%s\""), opt);

Errors should be a sentence.

> +	      else
> +		{
> +		  /* Trailing garbage.  This will be handled by
> +		     one of the callers.  */
> +		  *argp = start;
> +		  break;
> +		}
> +
> +	      /* 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 linespec argument" error before any missing
> +		 argument error.  */
> +	      if (oarg == NULL)
> +		error (_("missing argument for \"%s\""), opt);

Errors should be a sentence.

> +
> +	      /* The option/argument pair was successfully processed,
> +		 that memory now belongs to the explicit_linespec.  */
> +	      discard_cleanups (inner);
> +	    }
> +
> +	  /* A valid explicit linespec was constructed.  */
> +	  discard_cleanups (cleanup);
> +	  return els;
> +	}
> +    }
> +
> +  /* Not an explicit linespec.  */
> +  return NULL;
> +}
> +
> +/* Deep copy the explicit linespec given by SRC and return
> +   the copy.  */
> +
> +explicit_linespec *
> +copy_explicit_linespec (explicit_linespec *src)
> +{
> +  explicit_linespec *copy;
> +
> +  copy = XCNEW (explicit_linespec);
> +#define STRDUP_IF(MBR)				\
> +  do {						\
> +    if (src->MBR != NULL)			\
> +      copy->MBR = xstrdup (src->MBR);		\
> +  }						\
> +  while (0)

A nitpick but this macro does not have GNU Coding Style.

> +  STRDUP_IF (source_filename);
> +  STRDUP_IF (function_name);
> +  STRDUP_IF (label_name);
> +  STRDUP_IF (offset);
> +  STRDUP_IF (expression);
> +#undef STRDUP_IF
> +  return copy;
> +}
[...]

struct breakpoint:
    struct explicit_linespec *explicit;
init_breakpoint_sal:
    explicit_linespec *els,

style: Couldn't you use uniformly either struct explicit_linespec or
explicit_linespec (IMO struct explicit_linespec as GDB is using struct) and
also to either els or explicit (IMO explicit), sometimes you use just
explicit but sometimes explicit_linespec (free_explicit_linespec), IMO just use
explicit_linespec everywhere, too many new names for me for a single
patch/feature.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]