Commit | Line | Data |
---|---|---|
c7c1b3e9 | 1 | /* Data structures and API for event locations in GDB. |
618f726f | 2 | Copyright (C) 2013-2016 Free Software Foundation, Inc. |
c7c1b3e9 KS |
3 | |
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 3 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #include "defs.h" | |
20 | #include "gdb_assert.h" | |
21 | #include "location.h" | |
22 | #include "symtab.h" | |
23 | #include "language.h" | |
24 | #include "linespec.h" | |
25 | #include "cli/cli-utils.h" | |
26 | #include "probe.h" | |
27 | ||
28 | #include <ctype.h> | |
29 | #include <string.h> | |
30 | ||
31 | /* An event location used to set a stop event in the inferior. | |
32 | This structure is an amalgam of the various ways | |
33 | to specify where a stop event should be set. */ | |
34 | ||
35 | struct event_location | |
36 | { | |
37 | /* The type of this breakpoint specification. */ | |
38 | enum event_location_type type; | |
ebdad8fc | 39 | #define EL_TYPE(P) (P)->type |
c7c1b3e9 KS |
40 | |
41 | union | |
42 | { | |
43 | /* A generic "this is a string specification" for a location. | |
44 | This representation is used by both "normal" linespecs and | |
45 | probes. */ | |
46 | char *addr_string; | |
ebdad8fc KS |
47 | #define EL_LINESPEC(P) ((P)->u.addr_string) |
48 | #define EL_PROBE(P) ((P)->u.addr_string) | |
a06efdd6 KS |
49 | |
50 | /* An address in the inferior. */ | |
51 | CORE_ADDR address; | |
ebdad8fc | 52 | #define EL_ADDRESS(P) (P)->u.address |
00e52e53 KS |
53 | |
54 | /* An explicit location. */ | |
67994074 | 55 | struct explicit_location explicit_loc; |
ebdad8fc | 56 | #define EL_EXPLICIT(P) (&((P)->u.explicit_loc)) |
c7c1b3e9 KS |
57 | } u; |
58 | ||
59 | /* Cached string representation of this location. This is used, e.g., to | |
60 | save stop event locations to file. Malloc'd. */ | |
61 | char *as_string; | |
ebdad8fc | 62 | #define EL_STRING(P) ((P)->as_string) |
c7c1b3e9 KS |
63 | }; |
64 | ||
65 | /* See description in location.h. */ | |
66 | ||
67 | enum event_location_type | |
68 | event_location_type (const struct event_location *location) | |
69 | { | |
70 | return EL_TYPE (location); | |
71 | } | |
72 | ||
73 | /* See description in location.h. */ | |
74 | ||
00e52e53 | 75 | void |
67994074 | 76 | initialize_explicit_location (struct explicit_location *explicit_loc) |
00e52e53 | 77 | { |
67994074 KS |
78 | memset (explicit_loc, 0, sizeof (struct explicit_location)); |
79 | explicit_loc->line_offset.sign = LINE_OFFSET_UNKNOWN; | |
00e52e53 KS |
80 | } |
81 | ||
82 | /* See description in location.h. */ | |
83 | ||
c7c1b3e9 KS |
84 | struct event_location * |
85 | new_linespec_location (char **linespec) | |
86 | { | |
87 | struct event_location *location; | |
88 | ||
89 | location = XCNEW (struct event_location); | |
90 | EL_TYPE (location) = LINESPEC_LOCATION; | |
91 | if (*linespec != NULL) | |
92 | { | |
93 | char *p; | |
94 | char *orig = *linespec; | |
95 | ||
96 | linespec_lex_to_end (linespec); | |
97 | p = remove_trailing_whitespace (orig, *linespec); | |
98 | if ((p - orig) > 0) | |
99 | EL_LINESPEC (location) = savestring (orig, p - orig); | |
100 | } | |
101 | return location; | |
102 | } | |
103 | ||
104 | /* See description in location.h. */ | |
105 | ||
106 | const char * | |
107 | get_linespec_location (const struct event_location *location) | |
108 | { | |
109 | gdb_assert (EL_TYPE (location) == LINESPEC_LOCATION); | |
110 | return EL_LINESPEC (location); | |
111 | } | |
112 | ||
113 | /* See description in location.h. */ | |
114 | ||
a06efdd6 | 115 | struct event_location * |
305e13e6 JB |
116 | new_address_location (CORE_ADDR addr, const char *addr_string, |
117 | int addr_string_len) | |
a06efdd6 KS |
118 | { |
119 | struct event_location *location; | |
120 | ||
121 | location = XCNEW (struct event_location); | |
122 | EL_TYPE (location) = ADDRESS_LOCATION; | |
123 | EL_ADDRESS (location) = addr; | |
305e13e6 JB |
124 | if (addr_string != NULL) |
125 | EL_STRING (location) = xstrndup (addr_string, addr_string_len); | |
a06efdd6 KS |
126 | return location; |
127 | } | |
128 | ||
129 | /* See description in location.h. */ | |
130 | ||
131 | CORE_ADDR | |
132 | get_address_location (const struct event_location *location) | |
133 | { | |
134 | gdb_assert (EL_TYPE (location) == ADDRESS_LOCATION); | |
135 | return EL_ADDRESS (location); | |
136 | } | |
137 | ||
138 | /* See description in location.h. */ | |
139 | ||
305e13e6 JB |
140 | const char * |
141 | get_address_string_location (const struct event_location *location) | |
142 | { | |
143 | gdb_assert (EL_TYPE (location) == ADDRESS_LOCATION); | |
144 | return EL_STRING (location); | |
145 | } | |
146 | ||
147 | /* See description in location.h. */ | |
148 | ||
5b56227b KS |
149 | struct event_location * |
150 | new_probe_location (const char *probe) | |
151 | { | |
152 | struct event_location *location; | |
153 | ||
154 | location = XCNEW (struct event_location); | |
155 | EL_TYPE (location) = PROBE_LOCATION; | |
156 | if (probe != NULL) | |
157 | EL_PROBE (location) = xstrdup (probe); | |
158 | return location; | |
159 | } | |
160 | ||
161 | /* See description in location.h. */ | |
162 | ||
163 | const char * | |
164 | get_probe_location (const struct event_location *location) | |
165 | { | |
166 | gdb_assert (EL_TYPE (location) == PROBE_LOCATION); | |
167 | return EL_PROBE (location); | |
168 | } | |
169 | ||
170 | /* See description in location.h. */ | |
171 | ||
00e52e53 | 172 | struct event_location * |
67994074 | 173 | new_explicit_location (const struct explicit_location *explicit_loc) |
00e52e53 KS |
174 | { |
175 | struct event_location tmp; | |
176 | ||
177 | memset (&tmp, 0, sizeof (struct event_location)); | |
178 | EL_TYPE (&tmp) = EXPLICIT_LOCATION; | |
179 | initialize_explicit_location (EL_EXPLICIT (&tmp)); | |
67994074 | 180 | if (explicit_loc != NULL) |
00e52e53 | 181 | { |
67994074 | 182 | if (explicit_loc->source_filename != NULL) |
00e52e53 KS |
183 | { |
184 | EL_EXPLICIT (&tmp)->source_filename | |
67994074 | 185 | = explicit_loc->source_filename; |
00e52e53 KS |
186 | } |
187 | ||
67994074 | 188 | if (explicit_loc->function_name != NULL) |
00e52e53 | 189 | EL_EXPLICIT (&tmp)->function_name |
67994074 | 190 | = explicit_loc->function_name; |
00e52e53 | 191 | |
67994074 KS |
192 | if (explicit_loc->label_name != NULL) |
193 | EL_EXPLICIT (&tmp)->label_name = explicit_loc->label_name; | |
00e52e53 | 194 | |
67994074 KS |
195 | if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN) |
196 | EL_EXPLICIT (&tmp)->line_offset = explicit_loc->line_offset; | |
00e52e53 KS |
197 | } |
198 | ||
199 | return copy_event_location (&tmp); | |
200 | } | |
201 | ||
202 | /* See description in location.h. */ | |
203 | ||
204 | struct explicit_location * | |
205 | get_explicit_location (struct event_location *location) | |
206 | { | |
207 | gdb_assert (EL_TYPE (location) == EXPLICIT_LOCATION); | |
208 | return EL_EXPLICIT (location); | |
209 | } | |
210 | ||
211 | /* See description in location.h. */ | |
212 | ||
213 | const struct explicit_location * | |
214 | get_explicit_location_const (const struct event_location *location) | |
215 | { | |
216 | gdb_assert (EL_TYPE (location) == EXPLICIT_LOCATION); | |
217 | return EL_EXPLICIT (location); | |
218 | } | |
219 | ||
220 | /* This convenience function returns a malloc'd string which | |
67994074 | 221 | represents the location in EXPLICIT_LOC. |
00e52e53 KS |
222 | |
223 | AS_LINESPEC is non-zero if this string should be a linespec. | |
224 | Otherwise it will be output in explicit form. */ | |
225 | ||
226 | static char * | |
227 | explicit_to_string_internal (int as_linespec, | |
67994074 | 228 | const struct explicit_location *explicit_loc) |
00e52e53 KS |
229 | { |
230 | struct ui_file *buf; | |
231 | char space, *result; | |
232 | int need_space = 0; | |
233 | struct cleanup *cleanup; | |
234 | ||
235 | space = as_linespec ? ':' : ' '; | |
236 | buf = mem_fileopen (); | |
237 | cleanup = make_cleanup_ui_file_delete (buf); | |
238 | ||
67994074 | 239 | if (explicit_loc->source_filename != NULL) |
00e52e53 KS |
240 | { |
241 | if (!as_linespec) | |
242 | fputs_unfiltered ("-source ", buf); | |
67994074 | 243 | fputs_unfiltered (explicit_loc->source_filename, buf); |
00e52e53 KS |
244 | need_space = 1; |
245 | } | |
246 | ||
67994074 | 247 | if (explicit_loc->function_name != NULL) |
00e52e53 KS |
248 | { |
249 | if (need_space) | |
250 | fputc_unfiltered (space, buf); | |
251 | if (!as_linespec) | |
252 | fputs_unfiltered ("-function ", buf); | |
67994074 | 253 | fputs_unfiltered (explicit_loc->function_name, buf); |
00e52e53 KS |
254 | need_space = 1; |
255 | } | |
256 | ||
67994074 | 257 | if (explicit_loc->label_name != NULL) |
00e52e53 KS |
258 | { |
259 | if (need_space) | |
260 | fputc_unfiltered (space, buf); | |
261 | if (!as_linespec) | |
262 | fputs_unfiltered ("-label ", buf); | |
67994074 | 263 | fputs_unfiltered (explicit_loc->label_name, buf); |
00e52e53 KS |
264 | need_space = 1; |
265 | } | |
266 | ||
67994074 | 267 | if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN) |
00e52e53 KS |
268 | { |
269 | if (need_space) | |
270 | fputc_unfiltered (space, buf); | |
271 | if (!as_linespec) | |
272 | fputs_unfiltered ("-line ", buf); | |
273 | fprintf_filtered (buf, "%s%d", | |
67994074 KS |
274 | (explicit_loc->line_offset.sign == LINE_OFFSET_NONE ? "" |
275 | : (explicit_loc->line_offset.sign | |
00e52e53 | 276 | == LINE_OFFSET_PLUS ? "+" : "-")), |
67994074 | 277 | explicit_loc->line_offset.offset); |
00e52e53 KS |
278 | } |
279 | ||
280 | result = ui_file_xstrdup (buf, NULL); | |
281 | do_cleanups (cleanup); | |
282 | return result; | |
283 | } | |
284 | ||
285 | /* See description in location.h. */ | |
286 | ||
287 | char * | |
67994074 | 288 | explicit_location_to_string (const struct explicit_location *explicit_loc) |
00e52e53 | 289 | { |
67994074 | 290 | return explicit_to_string_internal (0, explicit_loc); |
00e52e53 KS |
291 | } |
292 | ||
293 | /* See description in location.h. */ | |
294 | ||
295 | char * | |
67994074 | 296 | explicit_location_to_linespec (const struct explicit_location *explicit_loc) |
00e52e53 | 297 | { |
67994074 | 298 | return explicit_to_string_internal (1, explicit_loc); |
00e52e53 KS |
299 | } |
300 | ||
301 | /* See description in location.h. */ | |
302 | ||
c7c1b3e9 KS |
303 | struct event_location * |
304 | copy_event_location (const struct event_location *src) | |
305 | { | |
306 | struct event_location *dst; | |
307 | ||
308 | dst = XCNEW (struct event_location); | |
309 | EL_TYPE (dst) = EL_TYPE (src); | |
310 | if (EL_STRING (src) != NULL) | |
311 | EL_STRING (dst) = xstrdup (EL_STRING (src)); | |
312 | ||
313 | switch (EL_TYPE (src)) | |
314 | { | |
315 | case LINESPEC_LOCATION: | |
316 | if (EL_LINESPEC (src) != NULL) | |
317 | EL_LINESPEC (dst) = xstrdup (EL_LINESPEC (src)); | |
318 | break; | |
319 | ||
a06efdd6 KS |
320 | case ADDRESS_LOCATION: |
321 | EL_ADDRESS (dst) = EL_ADDRESS (src); | |
322 | break; | |
323 | ||
00e52e53 KS |
324 | case EXPLICIT_LOCATION: |
325 | if (EL_EXPLICIT (src)->source_filename != NULL) | |
326 | EL_EXPLICIT (dst)->source_filename | |
327 | = xstrdup (EL_EXPLICIT (src)->source_filename); | |
328 | ||
329 | if (EL_EXPLICIT (src)->function_name != NULL) | |
330 | EL_EXPLICIT (dst)->function_name | |
331 | = xstrdup (EL_EXPLICIT (src)->function_name); | |
332 | ||
333 | if (EL_EXPLICIT (src)->label_name != NULL) | |
334 | EL_EXPLICIT (dst)->label_name = xstrdup (EL_EXPLICIT (src)->label_name); | |
335 | ||
336 | EL_EXPLICIT (dst)->line_offset = EL_EXPLICIT (src)->line_offset; | |
337 | break; | |
338 | ||
339 | ||
5b56227b KS |
340 | case PROBE_LOCATION: |
341 | if (EL_PROBE (src) != NULL) | |
342 | EL_PROBE (dst) = xstrdup (EL_PROBE (src)); | |
343 | break; | |
344 | ||
c7c1b3e9 KS |
345 | default: |
346 | gdb_assert_not_reached ("unknown event location type"); | |
347 | } | |
348 | ||
349 | return dst; | |
350 | } | |
351 | ||
352 | /* A cleanup function for struct event_location. */ | |
353 | ||
354 | static void | |
355 | delete_event_location_cleanup (void *data) | |
356 | { | |
357 | struct event_location *location = (struct event_location *) data; | |
358 | ||
359 | delete_event_location (location); | |
360 | } | |
361 | ||
362 | /* See description in location.h. */ | |
363 | ||
364 | struct cleanup * | |
365 | make_cleanup_delete_event_location (struct event_location *location) | |
366 | { | |
367 | return make_cleanup (delete_event_location_cleanup, location); | |
368 | } | |
369 | ||
370 | /* See description in location.h. */ | |
371 | ||
372 | void | |
373 | delete_event_location (struct event_location *location) | |
374 | { | |
375 | if (location != NULL) | |
376 | { | |
377 | xfree (EL_STRING (location)); | |
378 | ||
379 | switch (EL_TYPE (location)) | |
380 | { | |
381 | case LINESPEC_LOCATION: | |
382 | xfree (EL_LINESPEC (location)); | |
383 | break; | |
384 | ||
a06efdd6 KS |
385 | case ADDRESS_LOCATION: |
386 | /* Nothing to do. */ | |
387 | break; | |
388 | ||
00e52e53 KS |
389 | case EXPLICIT_LOCATION: |
390 | xfree (EL_EXPLICIT (location)->source_filename); | |
391 | xfree (EL_EXPLICIT (location)->function_name); | |
392 | xfree (EL_EXPLICIT (location)->label_name); | |
393 | break; | |
394 | ||
5b56227b KS |
395 | case PROBE_LOCATION: |
396 | xfree (EL_PROBE (location)); | |
397 | break; | |
398 | ||
c7c1b3e9 KS |
399 | default: |
400 | gdb_assert_not_reached ("unknown event location type"); | |
401 | } | |
402 | ||
403 | xfree (location); | |
404 | } | |
405 | } | |
406 | ||
407 | /* See description in location.h. */ | |
408 | ||
409 | const char * | |
410 | event_location_to_string (struct event_location *location) | |
411 | { | |
412 | if (EL_STRING (location) == NULL) | |
413 | { | |
414 | switch (EL_TYPE (location)) | |
415 | { | |
416 | case LINESPEC_LOCATION: | |
417 | if (EL_LINESPEC (location) != NULL) | |
418 | EL_STRING (location) = xstrdup (EL_LINESPEC (location)); | |
419 | break; | |
420 | ||
a06efdd6 KS |
421 | case ADDRESS_LOCATION: |
422 | EL_STRING (location) | |
423 | = xstrprintf ("*%s", | |
424 | core_addr_to_string (EL_ADDRESS (location))); | |
425 | break; | |
426 | ||
00e52e53 KS |
427 | case EXPLICIT_LOCATION: |
428 | EL_STRING (location) | |
429 | = explicit_location_to_string (EL_EXPLICIT (location)); | |
430 | break; | |
431 | ||
5b56227b KS |
432 | case PROBE_LOCATION: |
433 | EL_STRING (location) = xstrdup (EL_PROBE (location)); | |
434 | break; | |
435 | ||
c7c1b3e9 KS |
436 | default: |
437 | gdb_assert_not_reached ("unknown event location type"); | |
438 | } | |
439 | } | |
440 | ||
441 | return EL_STRING (location); | |
442 | } | |
443 | ||
87f0e720 KS |
444 | /* A lexer for explicit locations. This function will advance INP |
445 | past any strings that it lexes. Returns a malloc'd copy of the | |
446 | lexed string or NULL if no lexing was done. */ | |
447 | ||
448 | static char * | |
449 | explicit_location_lex_one (const char **inp, | |
450 | const struct language_defn *language) | |
451 | { | |
452 | const char *start = *inp; | |
453 | ||
454 | if (*start == '\0') | |
455 | return NULL; | |
456 | ||
457 | /* If quoted, skip to the ending quote. */ | |
458 | if (strchr (get_gdb_linespec_parser_quote_characters (), *start)) | |
459 | { | |
460 | char quote_char = *start; | |
461 | ||
462 | /* If the input is not an Ada operator, skip to the matching | |
463 | closing quote and return the string. */ | |
464 | if (!(language->la_language == language_ada | |
465 | && quote_char == '\"' && is_ada_operator (start))) | |
466 | { | |
467 | const char *end = find_toplevel_char (start + 1, quote_char); | |
468 | ||
469 | if (end == NULL) | |
470 | error (_("Unmatched quote, %s."), start); | |
471 | *inp = end + 1; | |
472 | return savestring (start + 1, *inp - start - 2); | |
473 | } | |
474 | } | |
475 | ||
476 | /* If the input starts with '-' or '+', the string ends with the next | |
477 | whitespace or comma. */ | |
478 | if (*start == '-' || *start == '+') | |
479 | { | |
480 | while (*inp[0] != '\0' && *inp[0] != ',' && !isspace (*inp[0])) | |
481 | ++(*inp); | |
482 | } | |
483 | else | |
484 | { | |
485 | /* Handle numbers first, stopping at the next whitespace or ','. */ | |
486 | while (isdigit (*inp[0])) | |
487 | ++(*inp); | |
488 | if (*inp[0] == '\0' || isspace (*inp[0]) || *inp[0] == ',') | |
489 | return savestring (start, *inp - start); | |
490 | ||
491 | /* Otherwise stop at the next occurrence of whitespace, '\0', | |
492 | keyword, or ','. */ | |
493 | *inp = start; | |
494 | while ((*inp)[0] | |
495 | && (*inp)[0] != ',' | |
496 | && !(isspace ((*inp)[0]) | |
497 | || linespec_lexer_lex_keyword (&(*inp)[1]))) | |
498 | { | |
499 | /* Special case: C++ operator,. */ | |
500 | if (language->la_language == language_cplus | |
501 | && strncmp (*inp, "operator", 8) | |
502 | && (*inp)[9] == ',') | |
503 | (*inp) += 9; | |
504 | ++(*inp); | |
505 | } | |
506 | } | |
507 | ||
508 | if (*inp - start > 0) | |
509 | return savestring (start, *inp - start); | |
510 | ||
511 | return NULL; | |
512 | } | |
513 | ||
514 | /* See description in location.h. */ | |
515 | ||
516 | struct event_location * | |
517 | string_to_explicit_location (const char **argp, | |
518 | const struct language_defn *language, | |
519 | int dont_throw) | |
520 | { | |
521 | struct cleanup *cleanup; | |
522 | struct event_location *location; | |
523 | ||
524 | /* It is assumed that input beginning with '-' and a non-digit | |
eeb1af43 KS |
525 | character is an explicit location. "-p" is reserved, though, |
526 | for probe locations. */ | |
87f0e720 KS |
527 | if (argp == NULL |
528 | || *argp == '\0' | |
529 | || *argp[0] != '-' | |
eeb1af43 KS |
530 | || !isalpha ((*argp)[1]) |
531 | || ((*argp)[0] == '-' && (*argp)[1] == 'p')) | |
87f0e720 KS |
532 | return NULL; |
533 | ||
534 | location = new_explicit_location (NULL); | |
535 | cleanup = make_cleanup_delete_event_location (location); | |
536 | ||
537 | /* Process option/argument pairs. dprintf_command | |
538 | requires that processing stop on ','. */ | |
539 | while ((*argp)[0] != '\0' && (*argp)[0] != ',') | |
540 | { | |
541 | int len; | |
542 | char *opt, *oarg; | |
543 | const char *start; | |
544 | struct cleanup *opt_cleanup, *oarg_cleanup; | |
545 | ||
546 | /* If *ARGP starts with a keyword, stop processing | |
547 | options. */ | |
548 | if (linespec_lexer_lex_keyword (*argp) != NULL) | |
549 | break; | |
550 | ||
551 | /* Mark the start of the string in case we need to rewind. */ | |
552 | start = *argp; | |
553 | ||
554 | /* Get the option string. */ | |
555 | opt = explicit_location_lex_one (argp, language); | |
556 | opt_cleanup = make_cleanup (xfree, opt); | |
557 | ||
558 | *argp = skip_spaces_const (*argp); | |
559 | ||
560 | /* Get the argument string. */ | |
561 | oarg = explicit_location_lex_one (argp, language); | |
562 | oarg_cleanup = make_cleanup (xfree, oarg); | |
563 | *argp = skip_spaces_const (*argp); | |
564 | ||
565 | /* Use the length of the option to allow abbreviations. */ | |
566 | len = strlen (opt); | |
567 | ||
568 | /* All options have a required argument. Checking for this required | |
569 | argument is deferred until later. */ | |
570 | if (strncmp (opt, "-source", len) == 0) | |
571 | EL_EXPLICIT (location)->source_filename = oarg; | |
572 | else if (strncmp (opt, "-function", len) == 0) | |
573 | EL_EXPLICIT (location)->function_name = oarg; | |
574 | else if (strncmp (opt, "-line", len) == 0) | |
575 | { | |
576 | if (oarg != NULL) | |
577 | { | |
578 | EL_EXPLICIT (location)->line_offset | |
579 | = linespec_parse_line_offset (oarg); | |
580 | do_cleanups (oarg_cleanup); | |
581 | do_cleanups (opt_cleanup); | |
582 | continue; | |
583 | } | |
584 | } | |
585 | else if (strncmp (opt, "-label", len) == 0) | |
586 | EL_EXPLICIT (location)->label_name = oarg; | |
587 | /* Only emit an "invalid argument" error for options | |
588 | that look like option strings. */ | |
589 | else if (opt[0] == '-' && !isdigit (opt[1])) | |
590 | { | |
591 | if (!dont_throw) | |
592 | error (_("invalid explicit location argument, \"%s\""), opt); | |
593 | } | |
594 | else | |
595 | { | |
596 | /* End of the explicit location specification. | |
597 | Stop parsing and return whatever explicit location was | |
598 | parsed. */ | |
599 | *argp = start; | |
600 | discard_cleanups (oarg_cleanup); | |
601 | do_cleanups (opt_cleanup); | |
602 | discard_cleanups (cleanup); | |
603 | return location; | |
604 | } | |
605 | ||
606 | /* It's a little lame to error after the fact, but in this | |
607 | case, it provides a much better user experience to issue | |
608 | the "invalid argument" error before any missing | |
609 | argument error. */ | |
610 | if (oarg == NULL && !dont_throw) | |
611 | error (_("missing argument for \"%s\""), opt); | |
612 | ||
613 | /* The option/argument pair was successfully processed; | |
614 | oarg belongs to the explicit location, and opt should | |
615 | be freed. */ | |
616 | discard_cleanups (oarg_cleanup); | |
617 | do_cleanups (opt_cleanup); | |
618 | } | |
619 | ||
620 | /* One special error check: If a source filename was given | |
621 | without offset, function, or label, issue an error. */ | |
622 | if (EL_EXPLICIT (location)->source_filename != NULL | |
623 | && EL_EXPLICIT (location)->function_name == NULL | |
624 | && EL_EXPLICIT (location)->label_name == NULL | |
625 | && (EL_EXPLICIT (location)->line_offset.sign == LINE_OFFSET_UNKNOWN) | |
626 | && !dont_throw) | |
627 | { | |
628 | error (_("Source filename requires function, label, or " | |
629 | "line offset.")); | |
630 | } | |
631 | ||
632 | discard_cleanups (cleanup); | |
633 | return location; | |
634 | } | |
635 | ||
c7c1b3e9 KS |
636 | /* See description in location.h. */ |
637 | ||
638 | struct event_location * | |
eeb1af43 KS |
639 | string_to_event_location_basic (char **stringp, |
640 | const struct language_defn *language) | |
c7c1b3e9 KS |
641 | { |
642 | struct event_location *location; | |
eeb1af43 | 643 | const char *arg, *orig, *cs; |
c7c1b3e9 | 644 | |
eeb1af43 KS |
645 | /* Try the input as a probe spec. */ |
646 | cs = *stringp; | |
647 | if (cs != NULL && probe_linespec_to_ops (&cs) != NULL) | |
a06efdd6 | 648 | { |
eeb1af43 KS |
649 | location = new_probe_location (*stringp); |
650 | *stringp += strlen (*stringp); | |
a06efdd6 KS |
651 | } |
652 | else | |
653 | { | |
eeb1af43 KS |
654 | /* Try an address location. */ |
655 | if (*stringp != NULL && **stringp == '*') | |
5b56227b | 656 | { |
87f0e720 | 657 | const char *arg, *orig; |
eeb1af43 | 658 | CORE_ADDR addr; |
87f0e720 | 659 | |
87f0e720 | 660 | orig = arg = *stringp; |
eeb1af43 KS |
661 | addr = linespec_expression_to_pc (&arg); |
662 | location = new_address_location (addr, orig, arg - orig); | |
663 | *stringp += arg - orig; | |
664 | } | |
665 | else | |
666 | { | |
667 | /* Everything else is a linespec. */ | |
668 | location = new_linespec_location (stringp); | |
5b56227b | 669 | } |
a06efdd6 KS |
670 | } |
671 | ||
c7c1b3e9 | 672 | return location; |
eeb1af43 KS |
673 | } |
674 | ||
675 | /* See description in location.h. */ | |
676 | ||
677 | struct event_location * | |
678 | string_to_event_location (char **stringp, | |
679 | const struct language_defn *language) | |
680 | { | |
681 | struct event_location *location; | |
682 | const char *arg, *orig; | |
683 | ||
684 | /* Try an explicit location. */ | |
685 | orig = arg = *stringp; | |
686 | location = string_to_explicit_location (&arg, language, 0); | |
687 | if (location != NULL) | |
688 | { | |
689 | /* It was a valid explicit location. Advance STRINGP to | |
690 | the end of input. */ | |
691 | *stringp += arg - orig; | |
692 | } | |
693 | else | |
694 | { | |
695 | /* Everything else is a "basic" linespec, address, or probe | |
696 | location. */ | |
697 | location = string_to_event_location_basic (stringp, language); | |
698 | } | |
699 | ||
700 | return location; | |
c7c1b3e9 KS |
701 | } |
702 | ||
703 | /* See description in location.h. */ | |
704 | ||
705 | int | |
706 | event_location_empty_p (const struct event_location *location) | |
707 | { | |
708 | switch (EL_TYPE (location)) | |
709 | { | |
710 | case LINESPEC_LOCATION: | |
711 | /* Linespecs are never "empty." (NULL is a valid linespec) */ | |
712 | return 0; | |
713 | ||
a06efdd6 KS |
714 | case ADDRESS_LOCATION: |
715 | return 0; | |
716 | ||
00e52e53 KS |
717 | case EXPLICIT_LOCATION: |
718 | return (EL_EXPLICIT (location) == NULL | |
719 | || (EL_EXPLICIT (location)->source_filename == NULL | |
720 | && EL_EXPLICIT (location)->function_name == NULL | |
721 | && EL_EXPLICIT (location)->label_name == NULL | |
722 | && (EL_EXPLICIT (location)->line_offset.sign | |
723 | == LINE_OFFSET_UNKNOWN))); | |
724 | ||
5b56227b KS |
725 | case PROBE_LOCATION: |
726 | return EL_PROBE (location) == NULL; | |
727 | ||
c7c1b3e9 KS |
728 | default: |
729 | gdb_assert_not_reached ("unknown event location type"); | |
730 | } | |
731 | } | |
732 | ||
733 | /* See description in location.h. */ | |
734 | ||
735 | void | |
736 | set_event_location_string (struct event_location *location, | |
737 | const char *string) | |
738 | { | |
739 | xfree (EL_STRING (location)); | |
740 | EL_STRING (location) = string == NULL ? NULL : xstrdup (string); | |
741 | } |