Commit | Line | Data |
---|---|---|
c7c1b3e9 KS |
1 | /* Data structures and API for event locations in GDB. |
2 | Copyright (C) 2013-2015 Free Software Foundation, Inc. | |
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 KS |
115 | struct event_location * |
116 | new_address_location (CORE_ADDR addr) | |
117 | { | |
118 | struct event_location *location; | |
119 | ||
120 | location = XCNEW (struct event_location); | |
121 | EL_TYPE (location) = ADDRESS_LOCATION; | |
122 | EL_ADDRESS (location) = addr; | |
123 | return location; | |
124 | } | |
125 | ||
126 | /* See description in location.h. */ | |
127 | ||
128 | CORE_ADDR | |
129 | get_address_location (const struct event_location *location) | |
130 | { | |
131 | gdb_assert (EL_TYPE (location) == ADDRESS_LOCATION); | |
132 | return EL_ADDRESS (location); | |
133 | } | |
134 | ||
135 | /* See description in location.h. */ | |
136 | ||
5b56227b KS |
137 | struct event_location * |
138 | new_probe_location (const char *probe) | |
139 | { | |
140 | struct event_location *location; | |
141 | ||
142 | location = XCNEW (struct event_location); | |
143 | EL_TYPE (location) = PROBE_LOCATION; | |
144 | if (probe != NULL) | |
145 | EL_PROBE (location) = xstrdup (probe); | |
146 | return location; | |
147 | } | |
148 | ||
149 | /* See description in location.h. */ | |
150 | ||
151 | const char * | |
152 | get_probe_location (const struct event_location *location) | |
153 | { | |
154 | gdb_assert (EL_TYPE (location) == PROBE_LOCATION); | |
155 | return EL_PROBE (location); | |
156 | } | |
157 | ||
158 | /* See description in location.h. */ | |
159 | ||
00e52e53 | 160 | struct event_location * |
67994074 | 161 | new_explicit_location (const struct explicit_location *explicit_loc) |
00e52e53 KS |
162 | { |
163 | struct event_location tmp; | |
164 | ||
165 | memset (&tmp, 0, sizeof (struct event_location)); | |
166 | EL_TYPE (&tmp) = EXPLICIT_LOCATION; | |
167 | initialize_explicit_location (EL_EXPLICIT (&tmp)); | |
67994074 | 168 | if (explicit_loc != NULL) |
00e52e53 | 169 | { |
67994074 | 170 | if (explicit_loc->source_filename != NULL) |
00e52e53 KS |
171 | { |
172 | EL_EXPLICIT (&tmp)->source_filename | |
67994074 | 173 | = explicit_loc->source_filename; |
00e52e53 KS |
174 | } |
175 | ||
67994074 | 176 | if (explicit_loc->function_name != NULL) |
00e52e53 | 177 | EL_EXPLICIT (&tmp)->function_name |
67994074 | 178 | = explicit_loc->function_name; |
00e52e53 | 179 | |
67994074 KS |
180 | if (explicit_loc->label_name != NULL) |
181 | EL_EXPLICIT (&tmp)->label_name = explicit_loc->label_name; | |
00e52e53 | 182 | |
67994074 KS |
183 | if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN) |
184 | EL_EXPLICIT (&tmp)->line_offset = explicit_loc->line_offset; | |
00e52e53 KS |
185 | } |
186 | ||
187 | return copy_event_location (&tmp); | |
188 | } | |
189 | ||
190 | /* See description in location.h. */ | |
191 | ||
192 | struct explicit_location * | |
193 | get_explicit_location (struct event_location *location) | |
194 | { | |
195 | gdb_assert (EL_TYPE (location) == EXPLICIT_LOCATION); | |
196 | return EL_EXPLICIT (location); | |
197 | } | |
198 | ||
199 | /* See description in location.h. */ | |
200 | ||
201 | const struct explicit_location * | |
202 | get_explicit_location_const (const struct event_location *location) | |
203 | { | |
204 | gdb_assert (EL_TYPE (location) == EXPLICIT_LOCATION); | |
205 | return EL_EXPLICIT (location); | |
206 | } | |
207 | ||
208 | /* This convenience function returns a malloc'd string which | |
67994074 | 209 | represents the location in EXPLICIT_LOC. |
00e52e53 KS |
210 | |
211 | AS_LINESPEC is non-zero if this string should be a linespec. | |
212 | Otherwise it will be output in explicit form. */ | |
213 | ||
214 | static char * | |
215 | explicit_to_string_internal (int as_linespec, | |
67994074 | 216 | const struct explicit_location *explicit_loc) |
00e52e53 KS |
217 | { |
218 | struct ui_file *buf; | |
219 | char space, *result; | |
220 | int need_space = 0; | |
221 | struct cleanup *cleanup; | |
222 | ||
223 | space = as_linespec ? ':' : ' '; | |
224 | buf = mem_fileopen (); | |
225 | cleanup = make_cleanup_ui_file_delete (buf); | |
226 | ||
67994074 | 227 | if (explicit_loc->source_filename != NULL) |
00e52e53 KS |
228 | { |
229 | if (!as_linespec) | |
230 | fputs_unfiltered ("-source ", buf); | |
67994074 | 231 | fputs_unfiltered (explicit_loc->source_filename, buf); |
00e52e53 KS |
232 | need_space = 1; |
233 | } | |
234 | ||
67994074 | 235 | if (explicit_loc->function_name != NULL) |
00e52e53 KS |
236 | { |
237 | if (need_space) | |
238 | fputc_unfiltered (space, buf); | |
239 | if (!as_linespec) | |
240 | fputs_unfiltered ("-function ", buf); | |
67994074 | 241 | fputs_unfiltered (explicit_loc->function_name, buf); |
00e52e53 KS |
242 | need_space = 1; |
243 | } | |
244 | ||
67994074 | 245 | if (explicit_loc->label_name != NULL) |
00e52e53 KS |
246 | { |
247 | if (need_space) | |
248 | fputc_unfiltered (space, buf); | |
249 | if (!as_linespec) | |
250 | fputs_unfiltered ("-label ", buf); | |
67994074 | 251 | fputs_unfiltered (explicit_loc->label_name, buf); |
00e52e53 KS |
252 | need_space = 1; |
253 | } | |
254 | ||
67994074 | 255 | if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN) |
00e52e53 KS |
256 | { |
257 | if (need_space) | |
258 | fputc_unfiltered (space, buf); | |
259 | if (!as_linespec) | |
260 | fputs_unfiltered ("-line ", buf); | |
261 | fprintf_filtered (buf, "%s%d", | |
67994074 KS |
262 | (explicit_loc->line_offset.sign == LINE_OFFSET_NONE ? "" |
263 | : (explicit_loc->line_offset.sign | |
00e52e53 | 264 | == LINE_OFFSET_PLUS ? "+" : "-")), |
67994074 | 265 | explicit_loc->line_offset.offset); |
00e52e53 KS |
266 | } |
267 | ||
268 | result = ui_file_xstrdup (buf, NULL); | |
269 | do_cleanups (cleanup); | |
270 | return result; | |
271 | } | |
272 | ||
273 | /* See description in location.h. */ | |
274 | ||
275 | char * | |
67994074 | 276 | explicit_location_to_string (const struct explicit_location *explicit_loc) |
00e52e53 | 277 | { |
67994074 | 278 | return explicit_to_string_internal (0, explicit_loc); |
00e52e53 KS |
279 | } |
280 | ||
281 | /* See description in location.h. */ | |
282 | ||
283 | char * | |
67994074 | 284 | explicit_location_to_linespec (const struct explicit_location *explicit_loc) |
00e52e53 | 285 | { |
67994074 | 286 | return explicit_to_string_internal (1, explicit_loc); |
00e52e53 KS |
287 | } |
288 | ||
289 | /* See description in location.h. */ | |
290 | ||
c7c1b3e9 KS |
291 | struct event_location * |
292 | copy_event_location (const struct event_location *src) | |
293 | { | |
294 | struct event_location *dst; | |
295 | ||
296 | dst = XCNEW (struct event_location); | |
297 | EL_TYPE (dst) = EL_TYPE (src); | |
298 | if (EL_STRING (src) != NULL) | |
299 | EL_STRING (dst) = xstrdup (EL_STRING (src)); | |
300 | ||
301 | switch (EL_TYPE (src)) | |
302 | { | |
303 | case LINESPEC_LOCATION: | |
304 | if (EL_LINESPEC (src) != NULL) | |
305 | EL_LINESPEC (dst) = xstrdup (EL_LINESPEC (src)); | |
306 | break; | |
307 | ||
a06efdd6 KS |
308 | case ADDRESS_LOCATION: |
309 | EL_ADDRESS (dst) = EL_ADDRESS (src); | |
310 | break; | |
311 | ||
00e52e53 KS |
312 | case EXPLICIT_LOCATION: |
313 | if (EL_EXPLICIT (src)->source_filename != NULL) | |
314 | EL_EXPLICIT (dst)->source_filename | |
315 | = xstrdup (EL_EXPLICIT (src)->source_filename); | |
316 | ||
317 | if (EL_EXPLICIT (src)->function_name != NULL) | |
318 | EL_EXPLICIT (dst)->function_name | |
319 | = xstrdup (EL_EXPLICIT (src)->function_name); | |
320 | ||
321 | if (EL_EXPLICIT (src)->label_name != NULL) | |
322 | EL_EXPLICIT (dst)->label_name = xstrdup (EL_EXPLICIT (src)->label_name); | |
323 | ||
324 | EL_EXPLICIT (dst)->line_offset = EL_EXPLICIT (src)->line_offset; | |
325 | break; | |
326 | ||
327 | ||
5b56227b KS |
328 | case PROBE_LOCATION: |
329 | if (EL_PROBE (src) != NULL) | |
330 | EL_PROBE (dst) = xstrdup (EL_PROBE (src)); | |
331 | break; | |
332 | ||
c7c1b3e9 KS |
333 | default: |
334 | gdb_assert_not_reached ("unknown event location type"); | |
335 | } | |
336 | ||
337 | return dst; | |
338 | } | |
339 | ||
340 | /* A cleanup function for struct event_location. */ | |
341 | ||
342 | static void | |
343 | delete_event_location_cleanup (void *data) | |
344 | { | |
345 | struct event_location *location = (struct event_location *) data; | |
346 | ||
347 | delete_event_location (location); | |
348 | } | |
349 | ||
350 | /* See description in location.h. */ | |
351 | ||
352 | struct cleanup * | |
353 | make_cleanup_delete_event_location (struct event_location *location) | |
354 | { | |
355 | return make_cleanup (delete_event_location_cleanup, location); | |
356 | } | |
357 | ||
358 | /* See description in location.h. */ | |
359 | ||
360 | void | |
361 | delete_event_location (struct event_location *location) | |
362 | { | |
363 | if (location != NULL) | |
364 | { | |
365 | xfree (EL_STRING (location)); | |
366 | ||
367 | switch (EL_TYPE (location)) | |
368 | { | |
369 | case LINESPEC_LOCATION: | |
370 | xfree (EL_LINESPEC (location)); | |
371 | break; | |
372 | ||
a06efdd6 KS |
373 | case ADDRESS_LOCATION: |
374 | /* Nothing to do. */ | |
375 | break; | |
376 | ||
00e52e53 KS |
377 | case EXPLICIT_LOCATION: |
378 | xfree (EL_EXPLICIT (location)->source_filename); | |
379 | xfree (EL_EXPLICIT (location)->function_name); | |
380 | xfree (EL_EXPLICIT (location)->label_name); | |
381 | break; | |
382 | ||
5b56227b KS |
383 | case PROBE_LOCATION: |
384 | xfree (EL_PROBE (location)); | |
385 | break; | |
386 | ||
c7c1b3e9 KS |
387 | default: |
388 | gdb_assert_not_reached ("unknown event location type"); | |
389 | } | |
390 | ||
391 | xfree (location); | |
392 | } | |
393 | } | |
394 | ||
395 | /* See description in location.h. */ | |
396 | ||
397 | const char * | |
398 | event_location_to_string (struct event_location *location) | |
399 | { | |
400 | if (EL_STRING (location) == NULL) | |
401 | { | |
402 | switch (EL_TYPE (location)) | |
403 | { | |
404 | case LINESPEC_LOCATION: | |
405 | if (EL_LINESPEC (location) != NULL) | |
406 | EL_STRING (location) = xstrdup (EL_LINESPEC (location)); | |
407 | break; | |
408 | ||
a06efdd6 KS |
409 | case ADDRESS_LOCATION: |
410 | EL_STRING (location) | |
411 | = xstrprintf ("*%s", | |
412 | core_addr_to_string (EL_ADDRESS (location))); | |
413 | break; | |
414 | ||
00e52e53 KS |
415 | case EXPLICIT_LOCATION: |
416 | EL_STRING (location) | |
417 | = explicit_location_to_string (EL_EXPLICIT (location)); | |
418 | break; | |
419 | ||
5b56227b KS |
420 | case PROBE_LOCATION: |
421 | EL_STRING (location) = xstrdup (EL_PROBE (location)); | |
422 | break; | |
423 | ||
c7c1b3e9 KS |
424 | default: |
425 | gdb_assert_not_reached ("unknown event location type"); | |
426 | } | |
427 | } | |
428 | ||
429 | return EL_STRING (location); | |
430 | } | |
431 | ||
87f0e720 KS |
432 | /* A lexer for explicit locations. This function will advance INP |
433 | past any strings that it lexes. Returns a malloc'd copy of the | |
434 | lexed string or NULL if no lexing was done. */ | |
435 | ||
436 | static char * | |
437 | explicit_location_lex_one (const char **inp, | |
438 | const struct language_defn *language) | |
439 | { | |
440 | const char *start = *inp; | |
441 | ||
442 | if (*start == '\0') | |
443 | return NULL; | |
444 | ||
445 | /* If quoted, skip to the ending quote. */ | |
446 | if (strchr (get_gdb_linespec_parser_quote_characters (), *start)) | |
447 | { | |
448 | char quote_char = *start; | |
449 | ||
450 | /* If the input is not an Ada operator, skip to the matching | |
451 | closing quote and return the string. */ | |
452 | if (!(language->la_language == language_ada | |
453 | && quote_char == '\"' && is_ada_operator (start))) | |
454 | { | |
455 | const char *end = find_toplevel_char (start + 1, quote_char); | |
456 | ||
457 | if (end == NULL) | |
458 | error (_("Unmatched quote, %s."), start); | |
459 | *inp = end + 1; | |
460 | return savestring (start + 1, *inp - start - 2); | |
461 | } | |
462 | } | |
463 | ||
464 | /* If the input starts with '-' or '+', the string ends with the next | |
465 | whitespace or comma. */ | |
466 | if (*start == '-' || *start == '+') | |
467 | { | |
468 | while (*inp[0] != '\0' && *inp[0] != ',' && !isspace (*inp[0])) | |
469 | ++(*inp); | |
470 | } | |
471 | else | |
472 | { | |
473 | /* Handle numbers first, stopping at the next whitespace or ','. */ | |
474 | while (isdigit (*inp[0])) | |
475 | ++(*inp); | |
476 | if (*inp[0] == '\0' || isspace (*inp[0]) || *inp[0] == ',') | |
477 | return savestring (start, *inp - start); | |
478 | ||
479 | /* Otherwise stop at the next occurrence of whitespace, '\0', | |
480 | keyword, or ','. */ | |
481 | *inp = start; | |
482 | while ((*inp)[0] | |
483 | && (*inp)[0] != ',' | |
484 | && !(isspace ((*inp)[0]) | |
485 | || linespec_lexer_lex_keyword (&(*inp)[1]))) | |
486 | { | |
487 | /* Special case: C++ operator,. */ | |
488 | if (language->la_language == language_cplus | |
489 | && strncmp (*inp, "operator", 8) | |
490 | && (*inp)[9] == ',') | |
491 | (*inp) += 9; | |
492 | ++(*inp); | |
493 | } | |
494 | } | |
495 | ||
496 | if (*inp - start > 0) | |
497 | return savestring (start, *inp - start); | |
498 | ||
499 | return NULL; | |
500 | } | |
501 | ||
502 | /* See description in location.h. */ | |
503 | ||
504 | struct event_location * | |
505 | string_to_explicit_location (const char **argp, | |
506 | const struct language_defn *language, | |
507 | int dont_throw) | |
508 | { | |
509 | struct cleanup *cleanup; | |
510 | struct event_location *location; | |
511 | ||
512 | /* It is assumed that input beginning with '-' and a non-digit | |
513 | character is an explicit location. */ | |
514 | if (argp == NULL | |
515 | || *argp == '\0' | |
516 | || *argp[0] != '-' | |
517 | || !isalpha ((*argp)[1])) | |
518 | return NULL; | |
519 | ||
520 | location = new_explicit_location (NULL); | |
521 | cleanup = make_cleanup_delete_event_location (location); | |
522 | ||
523 | /* Process option/argument pairs. dprintf_command | |
524 | requires that processing stop on ','. */ | |
525 | while ((*argp)[0] != '\0' && (*argp)[0] != ',') | |
526 | { | |
527 | int len; | |
528 | char *opt, *oarg; | |
529 | const char *start; | |
530 | struct cleanup *opt_cleanup, *oarg_cleanup; | |
531 | ||
532 | /* If *ARGP starts with a keyword, stop processing | |
533 | options. */ | |
534 | if (linespec_lexer_lex_keyword (*argp) != NULL) | |
535 | break; | |
536 | ||
537 | /* Mark the start of the string in case we need to rewind. */ | |
538 | start = *argp; | |
539 | ||
540 | /* Get the option string. */ | |
541 | opt = explicit_location_lex_one (argp, language); | |
542 | opt_cleanup = make_cleanup (xfree, opt); | |
543 | ||
544 | *argp = skip_spaces_const (*argp); | |
545 | ||
546 | /* Get the argument string. */ | |
547 | oarg = explicit_location_lex_one (argp, language); | |
548 | oarg_cleanup = make_cleanup (xfree, oarg); | |
549 | *argp = skip_spaces_const (*argp); | |
550 | ||
551 | /* Use the length of the option to allow abbreviations. */ | |
552 | len = strlen (opt); | |
553 | ||
554 | /* All options have a required argument. Checking for this required | |
555 | argument is deferred until later. */ | |
556 | if (strncmp (opt, "-source", len) == 0) | |
557 | EL_EXPLICIT (location)->source_filename = oarg; | |
558 | else if (strncmp (opt, "-function", len) == 0) | |
559 | EL_EXPLICIT (location)->function_name = oarg; | |
560 | else if (strncmp (opt, "-line", len) == 0) | |
561 | { | |
562 | if (oarg != NULL) | |
563 | { | |
564 | EL_EXPLICIT (location)->line_offset | |
565 | = linespec_parse_line_offset (oarg); | |
566 | do_cleanups (oarg_cleanup); | |
567 | do_cleanups (opt_cleanup); | |
568 | continue; | |
569 | } | |
570 | } | |
571 | else if (strncmp (opt, "-label", len) == 0) | |
572 | EL_EXPLICIT (location)->label_name = oarg; | |
573 | /* Only emit an "invalid argument" error for options | |
574 | that look like option strings. */ | |
575 | else if (opt[0] == '-' && !isdigit (opt[1])) | |
576 | { | |
577 | if (!dont_throw) | |
578 | error (_("invalid explicit location argument, \"%s\""), opt); | |
579 | } | |
580 | else | |
581 | { | |
582 | /* End of the explicit location specification. | |
583 | Stop parsing and return whatever explicit location was | |
584 | parsed. */ | |
585 | *argp = start; | |
586 | discard_cleanups (oarg_cleanup); | |
587 | do_cleanups (opt_cleanup); | |
588 | discard_cleanups (cleanup); | |
589 | return location; | |
590 | } | |
591 | ||
592 | /* It's a little lame to error after the fact, but in this | |
593 | case, it provides a much better user experience to issue | |
594 | the "invalid argument" error before any missing | |
595 | argument error. */ | |
596 | if (oarg == NULL && !dont_throw) | |
597 | error (_("missing argument for \"%s\""), opt); | |
598 | ||
599 | /* The option/argument pair was successfully processed; | |
600 | oarg belongs to the explicit location, and opt should | |
601 | be freed. */ | |
602 | discard_cleanups (oarg_cleanup); | |
603 | do_cleanups (opt_cleanup); | |
604 | } | |
605 | ||
606 | /* One special error check: If a source filename was given | |
607 | without offset, function, or label, issue an error. */ | |
608 | if (EL_EXPLICIT (location)->source_filename != NULL | |
609 | && EL_EXPLICIT (location)->function_name == NULL | |
610 | && EL_EXPLICIT (location)->label_name == NULL | |
611 | && (EL_EXPLICIT (location)->line_offset.sign == LINE_OFFSET_UNKNOWN) | |
612 | && !dont_throw) | |
613 | { | |
614 | error (_("Source filename requires function, label, or " | |
615 | "line offset.")); | |
616 | } | |
617 | ||
618 | discard_cleanups (cleanup); | |
619 | return location; | |
620 | } | |
621 | ||
c7c1b3e9 KS |
622 | /* See description in location.h. */ |
623 | ||
624 | struct event_location * | |
625 | string_to_event_location (char **stringp, | |
626 | const struct language_defn *language) | |
627 | { | |
628 | struct event_location *location; | |
629 | ||
a06efdd6 KS |
630 | /* First, check if the string is an address location. */ |
631 | if (*stringp != NULL && **stringp == '*') | |
632 | { | |
633 | const char *arg, *orig; | |
634 | CORE_ADDR addr; | |
635 | ||
636 | orig = arg = *stringp; | |
637 | addr = linespec_expression_to_pc (&arg); | |
638 | location = new_address_location (addr); | |
639 | *stringp += arg - orig; | |
640 | } | |
641 | else | |
642 | { | |
5b56227b KS |
643 | const char *cs; |
644 | ||
645 | /* Next, try the input as a probe spec. */ | |
646 | cs = *stringp; | |
647 | if (cs != NULL && probe_linespec_to_ops (&cs) != NULL) | |
648 | { | |
649 | location = new_probe_location (*stringp); | |
650 | *stringp += strlen (*stringp); | |
651 | } | |
652 | else | |
653 | { | |
87f0e720 KS |
654 | const char *arg, *orig; |
655 | ||
656 | /* Next, try an explicit location. */ | |
657 | orig = arg = *stringp; | |
658 | location = string_to_explicit_location (&arg, language, 0); | |
659 | if (location != NULL) | |
660 | { | |
661 | /* It was a valid explicit location. Advance STRINGP to | |
662 | the end of input. */ | |
663 | *stringp += arg - orig; | |
664 | } | |
665 | else | |
666 | { | |
667 | /* Everything else is a linespec. */ | |
668 | location = new_linespec_location (stringp); | |
669 | } | |
5b56227b | 670 | } |
a06efdd6 KS |
671 | } |
672 | ||
c7c1b3e9 KS |
673 | return location; |
674 | } | |
675 | ||
676 | /* See description in location.h. */ | |
677 | ||
678 | int | |
679 | event_location_empty_p (const struct event_location *location) | |
680 | { | |
681 | switch (EL_TYPE (location)) | |
682 | { | |
683 | case LINESPEC_LOCATION: | |
684 | /* Linespecs are never "empty." (NULL is a valid linespec) */ | |
685 | return 0; | |
686 | ||
a06efdd6 KS |
687 | case ADDRESS_LOCATION: |
688 | return 0; | |
689 | ||
00e52e53 KS |
690 | case EXPLICIT_LOCATION: |
691 | return (EL_EXPLICIT (location) == NULL | |
692 | || (EL_EXPLICIT (location)->source_filename == NULL | |
693 | && EL_EXPLICIT (location)->function_name == NULL | |
694 | && EL_EXPLICIT (location)->label_name == NULL | |
695 | && (EL_EXPLICIT (location)->line_offset.sign | |
696 | == LINE_OFFSET_UNKNOWN))); | |
697 | ||
5b56227b KS |
698 | case PROBE_LOCATION: |
699 | return EL_PROBE (location) == NULL; | |
700 | ||
c7c1b3e9 KS |
701 | default: |
702 | gdb_assert_not_reached ("unknown event location type"); | |
703 | } | |
704 | } | |
705 | ||
706 | /* See description in location.h. */ | |
707 | ||
708 | void | |
709 | set_event_location_string (struct event_location *location, | |
710 | const char *string) | |
711 | { | |
712 | xfree (EL_STRING (location)); | |
713 | EL_STRING (location) = string == NULL ? NULL : xstrdup (string); | |
714 | } |