Always pass lower-case filenames to wine_dll_load().
[wine] / library / debug.c
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 */
59 void *__wine_dbg_register( char * const *channels, int nb )
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 */
83 void __wine_dbg_unregister( void *channel )
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 }