diff options
Diffstat (limited to 'gdb/gdb-events.sh')
-rwxr-xr-x | gdb/gdb-events.sh | 568 |
1 files changed, 568 insertions, 0 deletions
diff --git a/gdb/gdb-events.sh b/gdb/gdb-events.sh new file mode 100755 index 00000000000..ab70bb19d06 --- /dev/null +++ b/gdb/gdb-events.sh @@ -0,0 +1,568 @@ +#!/bin/sh + +# User Interface Events. +# Copyright 1999 Free Software Foundation, Inc. +# +# Contributed by Cygnus Solutions. +# +# This file is part of GDB. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# +# What happens next: +# + +# The gdb-events.h/gdb-events.c files this script generates are commited +# and published. + +# Any UI module that is installing events is changed so that the +# events are installed using the ``set_gdb_events()'' and +# ``gdb_event_hooks()'' interfaces. There could prove to be an issue +# here with respect to annotate. We might need to accomodate a hook +# stack that allows several ui blocks to install their own events. + +# Each of the variable events (as currently generated) is converteded +# to either a straight function call or a function call with a +# predicate. + + +IFS=: + +read="class returntype function formal actual attrib" + +function_list () +{ + # category: + # # -> disable + # * -> compatibility - pointer variable that is initialized + # by set_gdb_events(). + # ? -> Predicate and function proper. + # f -> always call (must have a void returntype) + # return-type + # name + # formal argument list + # actual argument list + # attributes + # description + cat <<EOF | +f:void:breakpoint_create:int b:b +f:void:breakpoint_delete:int b:b +f:void:breakpoint_modify:int b:b +#*:void:annotate_starting_hook:void +#*:void:annotate_stopped_hook:void +#*:void:annotate_signalled_hook:void +#*:void:annotate_signal_hook:void +#*:void:annotate_exited_hook:void +##*:void:print_register_hook:int +##*:CORE_ADDR:find_toc_address_hook:CORE_ADDR +##*:void:sparc_print_register_hook:int regno:regno +#*:void:target_resume_hook:void +#*:void:target_wait_loop_hook:void +#*:void:init_gdb_hook:char *argv0:argv0 +#*:void:command_loop_hook:void +#*:void:fputs_unfiltered_hook:const char *linebuff,GDB_FILE *stream:linebuff, stream +#*:void:print_frame_info_listing_hook:struct symtab *s, int line, int stopline, int noerror:s, line, stopline, noerror +#*:int:query_hook:const char *query, va_list args:query, args +#*:void:warning_hook:const char *string, va_list args:string, args +#*:void:flush_hook:GDB_FILE *stream:stream +#*:void:target_output_hook:char *b:b +#*:void:interactive_hook:void +#*:void:registers_changed_hook:void +#*:void:readline_begin_hook:char *format, ...:format +#*:char *:readline_hook:char *prompt:prompt +#*:void:readline_end_hook:void +#*:void:register_changed_hook:int regno:regno +#*:void:memory_changed_hook:CORE_ADDR addr, int len:addr, len +#*:void:context_hook:int num:num +#*:int:target_wait_hook:int pid, struct target_waitstatus *status:pid, status +#*:void:call_command_hook:struct cmd_list_element *c, char *cmd, int from_tty:c, cmd, from_tty +#*:NORETURN void:error_hook:void:: ATTR_NORETURN +#*:void:error_begin_hook:void +##*:int:target_architecture_hook:const struct bfd_arch_info * +#*:void:exec_file_display_hook:char *filename:filename +#*:void:file_changed_hook:char *filename:filename +##*:void:specify_exec_file_hook: +#*:int:gdb_load_progress_hook:char *section, unsigned long num:section, num +#*:void:pre_add_symbol_hook:char *name:name +#*:void:post_add_symbol_hook:void +#*:void:selected_frame_level_changed_hook:int level:level +#*:int:gdb_loop_hook:int signo:signo +##*:void:solib_create_inferior_hook:void +##*:void:xcoff_relocate_symtab_hook:unsigned int +EOF + grep -v '^#' +} + +copyright () +{ + cat <<EOF +/* User Interface Events. + Copyright 1999 Free Software Foundation, Inc. + + Contributed by Cygnus Solutions. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Work in progress */ + +/* This file was created with the aid of \`\`gdb-events.sh''. + + The bourn shell script \`\`gdb-events.sh'' creates the files + \`\`new-gdb-events.c'' and \`\`new-gdb-events.h and then compares + them against the existing \`\`gdb-events.[hc]''. Any differences + found being reported. + + If editing this file, please also run gdb-events.sh and merge any + changes into that script. Conversely, when making sweeping changes + to this file, modifying gdb-events.sh and using its output may + prove easier. */ + +EOF +} + +# +# The .h file +# + +exec > new-gdb-events.h +copyright +cat <<EOF + +#ifndef GDB_EVENTS_H +#define GDB_EVENTS_H + +#ifndef WITH_GDB_EVENTS +#define WITH_GDB_EVENTS 1 +#endif +EOF + +# pointer declarations +echo "" +echo "" +cat <<EOF +/* COMPAT: pointer variables for old, unconverted events. + A call to set_gdb_events() will automatically update these. */ +EOF +echo "" +function_list | while eval read $read +do + case "${class}" in + "*" ) + echo "extern ${returntype} (*${function}_event) (${formal})${attrib};" + ;; + esac +done + +# function typedef's +echo "" +echo "" +cat <<EOF +/* Type definition of all hook functions. + Recommended pratice is to first declare each hook function using + the below ftype and then define it. */ +EOF +echo "" +function_list | while eval read $read +do + echo "typedef ${returntype} (gdb_events_${function}_ftype) (${formal});" +done + +# gdb_events object +echo "" +echo "" +cat <<EOF +/* gdb-events: object. */ +EOF +echo "" +echo "struct gdb_events" +echo " {" +function_list | while eval read $read +do + echo " gdb_events_${function}_ftype *${function}${attrib};" +done +echo " };" + +# function declarations +echo "" +echo "" +cat <<EOF +/* Interface into events functions. + Where a *_p() predicate is present, it must called before calling + the hook proper. */ +EOF +function_list | while eval read $read +do + case "${class}" in + "*" ) continue ;; + "?" ) + echo "extern int ${function}_p (void);" + echo "extern ${returntype} ${function}_event (${formal})${attrib};" + ;; + "f" ) + echo "extern ${returntype} ${function}_event (${formal})${attrib};" + ;; + esac +done + +# function macros +echo "" +echo "" +cat <<EOF +/* When GDB_EVENTS are not being used, completly disable them. */ +EOF +echo "" +echo "#if !WITH_GDB_EVENTS" +function_list | while eval read $read +do + case "${class}" in + "*" ) continue ;; + "?" ) + echo "#define ${function}_event_p() 0" + echo "#define ${function}_event(${actual}) 0" + ;; + "f" ) + echo "#define ${function}_event(${actual}) 0" + ;; + esac +done +echo "#endif" + +# our set function +cat <<EOF + +/* Install custom gdb-events hooks. */ +extern void set_gdb_event_hooks (struct gdb_events *vector); + +/* Deliver any pending events. */ +extern void gdb_events_deliver (struct gdb_events *vector); + +#if !WITH_GDB_EVENTS +#define set_gdb_events(x) 0 +#define set_gdb_event_hooks(x) 0 +#define gdb_events_deliver(x) 0 +#endif +EOF + +# close it off +echo "" +echo "#endif" +exec 1>&2 +#../move-if-change new-gdb-events.h gdb-events.h +if ! test -r gdb-events.h +then + echo "File missing? mv new-gdb-events.h gdb-events.h" 1>&2 +elif ! diff -c gdb-events.h new-gdb-events.h +then + echo "gdb-events.h changed? cp new-gdb-events.h gdb-events.h" 1>&2 +fi + + + +# +# C file +# + +exec > new-gdb-events.c +copyright +cat <<EOF + +#include "defs.h" +#include "gdb-events.h" +#include "gdbcmd.h" + +#undef XMALLOC +#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE))) + +#if WITH_GDB_EVENTS +static struct gdb_events null_event_hooks; +static struct gdb_events queue_event_hooks; +static struct gdb_events *current_event_hooks = &null_event_hooks; +#endif + +int gdb_events_debug; +EOF + +# global pointer variables - always have this +#echo "" +#function_list | while eval read $read +#do +# case "${class}" in +# "*" ) +# echo "${returntype} (*${function}_event) (${formal})${attrib} = 0;" +# ;; +# esac +#done + +# function bodies +echo "" +echo "#if WITH_GDB_EVENTS" +function_list | while eval read $read +do + case "${class}" in + "*" ) continue ;; + "?" ) + echo "" + echo "int" + echo "${function}_event_p (${formal})" + echo "{" + echo " return current_event_hooks->${function};" + echo "}" + echo "" + echo "${returntype}" + echo "${function}_event (${formal})" + echo "{" + echo " return current_events->${function} (${actual});" + echo "}" + ;; + "f" ) + echo "" + echo "void" + echo "${function}_event (${formal})" + echo "{" + echo " if (gdb_events_debug)" + echo " fprintf_unfiltered (gdb_stdlog, \"${function}_event\\n\");" + echo " if (!current_event_hooks->${function})" + echo " return;" + echo " current_event_hooks->${function} (${actual});" + echo "}" + ;; + esac +done +echo "" +echo "#endif" + +# Set hooks function +echo "" +cat <<EOF +#if WITH_GDB_EVENTS +void +set_gdb_event_hooks (struct gdb_events *vector) +{ + if (vector == NULL) + current_event_hooks = &queue_event_hooks; + else + current_event_hooks = vector; +EOF +function_list | while eval read $read +do + case "${class}" in + "*" ) + echo " ${function}_event = hooks->${function};" + ;; + esac +done +cat <<EOF +} +#endif +EOF + +# event type +echo "" +cat <<EOF +enum gdb_event + { +EOF +function_list | while eval read $read +do + case "${class}" in + "f" ) + echo " ${function}," + ;; + esac +done +cat <<EOF + nr_gdb_events + }; +EOF + +# event data +echo "" +function_list | while eval read $read +do + case "${class}" in + "f" ) + echo "struct ${function}" + echo " {" + echo " `echo ${formal} | tr '[,]' '[;]'`;" + echo " };" + echo "" + ;; + esac +done + +# event queue +cat <<EOF +struct event + { + enum gdb_event type; + struct event *next; + union + { +EOF +function_list | while eval read $read +do + case "${class}" in + "f" ) + echo " struct ${function} ${function};" + ;; + esac +done +cat <<EOF + } + data; + }; +struct event *pending_events; +struct event *delivering_events; +EOF + +# append +echo "" +cat <<EOF +static void +append (struct event *new_event) +{ + struct event **event = &pending_events; + while ((*event) != NULL) + event = &((*event)->next); + (*event) = new_event; + (*event)->next = NULL; +} +EOF + +# schedule a given event +function_list | while eval read $read +do + case "${class}" in + "f" ) + echo "" + echo "static void" + echo "queue_${function} (${formal})" + echo "{" + echo " struct event *event = XMALLOC (struct event);" + echo " event->type = ${function};" + for arg in `echo ${actual} | tr '[,]' '[ ]'`; do + echo " event->data.${function}.${arg} = ${arg};" + done + echo " append (event);" + echo "}" + ;; + esac +done + +# deliver +echo "" +cat <<EOF +void +gdb_events_deliver (struct gdb_events *vector) +{ + /* Just zap any events left around from last time. */ + while (delivering_events != NULL) + { + struct event *event = delivering_events; + delivering_events = event->next; + free (event); + } + /* Process any pending events. Because one of the deliveries could + bail out we move everything off of the pending queue onto an + in-progress queue where it can, later, be cleaned up if + necessary. */ + delivering_events = pending_events; + pending_events = NULL; + while (delivering_events != NULL) + { + struct event *event = delivering_events; + switch (event->type) + { +EOF +function_list | while eval read $read +do + case "${class}" in + "f" ) + echo " case ${function}:" + echo " vector->${function}" + sep=" (" + ass="" + for arg in `echo ${actual} | tr '[,]' '[ ]'`; do + ass="${ass}${sep}event->data.${function}.${arg}" + sep=", + " + done + echo "${ass});" + echo " break;" + ;; + esac +done +cat <<EOF + } + delivering_events = event->next; + free (event); + } +} +EOF + +# Finally the initialization +echo "" +cat <<EOF +void _initialize_gdb_events (void); +void +_initialize_gdb_events (void) +{ +#if WITH_GDB_EVENTS +EOF +function_list | while eval read $read +do + case "${class}" in + "f" ) + echo " queue_event_hooks.${function} = queue_${function};" + ;; + esac +done +cat <<EOF +#endif + add_show_from_set (add_set_cmd ("eventdebug", + class_maintenance, + var_zinteger, + (char *)&gdb_events_debug, + "Set event debugging.\n\\ +When non-zero, event/notify debugging is enabled.", &setlist), + &showlist); +} +EOF + +# close things off +exec 1>&2 +#../move-if-change new-gdb-events.c gdb-events.c +if ! test -r gdb-events.c +then + echo "File missing? mv new-gdb-events.c gdb-events.c" 1>&2 +elif ! diff -c gdb-events.c new-gdb-events.c +then + echo "gdb-events.c changed? cp new-gdb-events.c gdb-events.c" 1>&2 +fi |