Alexandre Julliard | 94613ab | 2000-11-05 04:51:34 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Management of the debugging channels |
| 3 | * |
| 4 | * Copyright 2000 Alexandre Julliard |
| 5 | */ |
| 6 | |
| 7 | #include <stdlib.h> |
| 8 | #include <string.h> |
| 9 | #include <unistd.h> |
| 10 | #include <ctype.h> |
| 11 | |
| 12 | struct dll |
| 13 | { |
| 14 | struct dll *next; /* linked list of dlls */ |
| 15 | struct dll *prev; |
| 16 | char * const *channels; /* array of channels */ |
| 17 | int nb_channels; /* number of channels in array */ |
| 18 | }; |
| 19 | |
| 20 | static struct dll *first_dll; |
| 21 | |
| 22 | struct option |
| 23 | { |
| 24 | struct option *next; /* next option in list */ |
| 25 | unsigned char set; /* bits to set */ |
| 26 | unsigned char clear; /* bits to clear */ |
| 27 | char name[14]; /* channel name, or empty for "all" */ |
| 28 | }; |
| 29 | |
| 30 | static struct option *first_option; |
| 31 | static struct option *last_option; |
| 32 | |
| 33 | |
| 34 | static int cmp_name( const void *p1, const void *p2 ) |
| 35 | { |
| 36 | const char *name = p1; |
| 37 | const char * const *chan = p2; |
| 38 | return strcmp( name, *chan + 1 ); |
| 39 | } |
| 40 | |
| 41 | /* apply a debug option to the channels of a given dll */ |
| 42 | static void apply_option( struct dll *dll, const struct option *opt ) |
| 43 | { |
| 44 | if (opt->name[0]) |
| 45 | { |
| 46 | char **dbch = bsearch( opt->name, dll->channels, dll->nb_channels, |
| 47 | sizeof(*dll->channels), cmp_name ); |
| 48 | if (dbch) **dbch = (**dbch & ~opt->clear) | opt->set; |
| 49 | } |
| 50 | else /* all */ |
| 51 | { |
| 52 | int i; |
| 53 | for (i = 0; i < dll->nb_channels; i++) |
| 54 | dll->channels[i][0] = (dll->channels[i][0] & ~opt->clear) | opt->set; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | /* register a new set of channels for a dll */ |
Alexandre Julliard | e087508 | 2000-11-08 04:33:20 +0000 | [diff] [blame] | 59 | void *__wine_dbg_register( char * const *channels, int nb ) |
Alexandre Julliard | 94613ab | 2000-11-05 04:51:34 +0000 | [diff] [blame] | 60 | { |
| 61 | struct option *opt = first_option; |
| 62 | struct dll *dll = malloc( sizeof(*dll) ); |
| 63 | if (dll) |
| 64 | { |
| 65 | dll->channels = channels; |
| 66 | dll->nb_channels = nb; |
| 67 | dll->prev = NULL; |
| 68 | if ((dll->next = first_dll)) dll->next->prev = dll; |
| 69 | first_dll = dll; |
| 70 | |
| 71 | /* apply existing options to this dll */ |
| 72 | while (opt) |
| 73 | { |
| 74 | apply_option( dll, opt ); |
| 75 | opt = opt->next; |
| 76 | } |
| 77 | } |
| 78 | return dll; |
| 79 | } |
| 80 | |
| 81 | |
| 82 | /* unregister a set of channels; must pass the pointer obtained from wine_dbg_register */ |
Alexandre Julliard | e087508 | 2000-11-08 04:33:20 +0000 | [diff] [blame] | 83 | void __wine_dbg_unregister( void *channel ) |
Alexandre Julliard | 94613ab | 2000-11-05 04:51:34 +0000 | [diff] [blame] | 84 | { |
| 85 | struct dll *dll = channel; |
| 86 | if (dll) |
| 87 | { |
| 88 | if (dll->next) dll->next->prev = dll->prev; |
| 89 | if (dll->prev) dll->prev->next = dll->next; |
| 90 | else first_dll = dll->next; |
| 91 | free( dll ); |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | |
| 96 | /* add a new debug option at the end of the option list */ |
| 97 | void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear ) |
| 98 | { |
| 99 | struct dll *dll = first_dll; |
| 100 | struct option *opt; |
| 101 | |
| 102 | if (!(opt = malloc( sizeof(*opt) ))) return; |
| 103 | opt->next = NULL; |
| 104 | opt->set = set; |
| 105 | opt->clear = clear; |
| 106 | strncpy( opt->name, name, sizeof(opt->name) ); |
| 107 | opt->name[sizeof(opt->name)-1] = 0; |
| 108 | if (last_option) last_option->next = opt; |
| 109 | else first_option = opt; |
| 110 | last_option = opt; |
| 111 | |
| 112 | /* apply option to all existing dlls */ |
| 113 | while (dll) |
| 114 | { |
| 115 | apply_option( dll, opt ); |
| 116 | dll = dll->next; |
| 117 | } |
| 118 | } |