| Note: the debugging interface is under development. Please do not make |
| changes to it yet as I will do major changes in the next few weeks. |
| To make my life easier, PLEASE follow the guidelines described in |
| this document. If you have some ideas that you would like to |
| incorporate, please contact me first. |
| Please read the document before writing new code. |
| Also, DO NOT USE fprintf (or printf) to output things. All these |
| will have to be translated to dprintf_ calls and there are already |
| about 3000 of them! Also, instead of writing FIXMEs in the source, |
| output a dprintf_fixme message. But read on... |
| 25 Feb 1998, Dimitrie O. Paun <dimi@cs.toronto.edu> |
| |
| |
| Debugging classes |
| ----------------- |
| |
| The debugging messages are divided into 4 classes: |
| |
| fixme -- Messages in this class relate to behavior of Wine that does |
| not correspond to standard Windows behavior and that should |
| be fixed. |
| Examples: stubs, semi-implemented features, etc. |
| |
| err -- Messages in this class relate to serious errors in Wine. |
| This sort of messages are close to asserts -- that is, |
| you should output a 'err' message when the code detects a |
| condition which should not happen. |
| Examples: unexpected change in internal state, etc. |
| |
| warn -- This are warning messages. You should report a warning when |
| something unwanted happen but the function behaves properly. |
| That is, output a warning when you encounter something |
| unexpected (ex: could not open a file) but the function deals |
| correctly with the situation (that is, according to the docs). |
| If you do not deal correctly with it, output a fixme. |
| Examples: fail to access a resource required by the app, etc. |
| |
| info -- This are detailed debugging messages that are mainly useful |
| to debug a component. This are usually turned off. |
| Examples: everything else that does not fall in one of the |
| above mentioned categories and the user does not |
| need to know about it. This sort of messages simply |
| outputs something about the state of some component |
| that is of interest mainly to the developer of that |
| component. |
| |
| We will refer to a generic class as yyy. |
| |
| The user has the capability to turn on or off messages in a particular |
| class. You can expect the following patters of usage (but note that |
| any combination is possible): |
| -- when you debug a component, all classes (info,warn,err,fixme) |
| will be enabled. |
| -- during the pre-alpha (maybe alpha) stage of Wine, most likely |
| the info class will be disabled by default, but all others |
| (warn,err,fixme) will be enabled by default. |
| -- when Wine will become stable, most likely the info and warn |
| classes will be disabled by default, but all err and fixme |
| will be enabled by default. |
| -- in some installations that want the smallest footprint |
| and where the debug information is of no interest, |
| all classes may be disabled by default. |
| |
| Of course, the user will have the runtime ability to override these |
| defaults. However, this ability may be turned off and certain classes |
| of messages may be completely disabled at compile time to reduce the |
| size of Wine. |
| |
| Debugging channels |
| ------------------ |
| |
| Also, we divide the debugging messages per component. Each component |
| is assigned a debugging channel (or type). The identifier of the |
| channel must be a valid C identifier but note that it may also be a |
| reserve word like int or static. |
| |
| Examples of debugging channels/types: |
| reg, updown, string |
| |
| We will refer to a generic channel as xxx. |
| |
| Note: for those who know the old interface, the channel/type is |
| what followed the _ in the dprintf_xxx statements. |
| For example, to output a message on the debugging channel |
| reg in the old interface you would have to write: |
| |
| dprintf_reg(stddeb, "Could not access key!\n"); |
| |
| In the new interface, we drop the stddeb as it is implicit. |
| However, we add an orthogonal piece of information to the |
| message: its class. This is very important as it will allow |
| us to selectively turn on or off certain messages based on |
| type of information they report. For this reason it is VERY |
| important to choose the right class for the message. |
| Anyhow, suppose we figured that this message should belong |
| in the warn class, so in the new interface, you write: |
| |
| dprintf_warn(reg, "Could not access key!\n"); |
| |
| --- |
| |
| How to use it |
| ------------- |
| |
| So, to output a message (class yyy) on channel xxx, do: |
| |
| #include "debug.h" |
| |
| .... |
| |
| dprintf_yyy(xxx, "<message>", ...); |
| |
| |
| Some examples from the code: |
| |
| #include "debug.h" |
| |
| ... |
| |
| dprintf_info(crtdll, |
| "CRTDLL_setbuf(file %p buf %p)\n", |
| file, buf); |
| |
| dprintf_warn(aspi, "Error opening device errno=%d\n", save_error); |
| |
| |
| If you need to declare a new debugging channel, do: |
| %tools/make_debug |
| in the root directory of Wine. |
| |
| Note that this will result in almost complete recompilation of Wine. |
| |
| Notes: |
| 1. Please pay attention to which class you assign the message. |
| It is very, Very, VERY important to get the class right. |
| There are only 4 classes, so it is not hard. The reason |
| it is important to get it right is that too much information |
| is no information. For example, if you put things into the |
| warn class that should really be in the info class, the |
| output will be too big and this will force the user to |
| turn of warnings. But this way he will fail to see the important |
| ones. Also, if you put warnings into the info class lets say, |
| he will most likely miss those because usually the info class |
| is turned off. A similar argument can be made if you mix any |
| other two classes. |
| 2. ALL LINES MUST END WITH A NEWLINE!!! If you can NOT output |
| everything that you want in the line with only one dprintf_xxx |
| statement, then you need to build the string in memory. |
| Please read the section below "In-memory messages" on the |
| preferred way to do it. PLEASE USE THAT INTERFACE TO BUILD |
| MESSAGES IN MEMORY. The reason is that we are not sure that |
| we like it and having everything in one format will facilitate |
| the (automatic) translation to a better interface. |
| |
| |
| |
| Are we debugging? |
| ----------------- |
| |
| To test whether the debugging output of class yyy on channel xxx is |
| enabled, do: |
| |
| debugging_yyy(xxx) |
| |
| Examples: |
| |
| if(debugging_info(atom)){ |
| ...blah... |
| } |
| |
| |
| |
| In-memory messages |
| ------------------ |
| |
| If you NEED to build the message from multiple calls, you need to |
| build it in memory. To do that, you should use the following |
| interface: |
| |
| - declare a string (where you are allowed to declare C variables) |
| as follows: |
| dbg_decl_str(name, len); |
| where name is the name of the string (you should use the channel |
| name on which you are going to output it) |
| |
| - print in it with: |
| dsprintf(name, "<message>", ...); |
| which is just like a sprintf function but instead of a C string as |
| first parameter it takes the name you used to declare it. |
| |
| - obtain a pointer to the string with: |
| dbg_str(name) |
| |
| - reset the string (if you want to reuse it with): |
| dbg_reset_str(name); |
| |
| Example (modified from the code): |
| |
| void some_func(tabs) |
| { |
| INT32 i; |
| LPINT16 p = (LPINT16)tabs; |
| dbg_decl_str(listbox, 256); /* declare the string */ |
| |
| for (i = 0; i < descr->nb_tabs; i++) { |
| descr->tabs[i] = *p++<<1; |
| if(debugging_info(listbox)) /* write in it only if |
| dsprintf(listbox, "%hd ", descr->tabs[i]); /* we are gonna output it */ |
| } |
| dprintf_info(listbox, "Listbox %04x: settabstops %s\n", |
| wnd->hwndSelf, dbg_str(listbox)); /* output the whole thing */ |
| } |
| |
| If you need to use it two times in the same scope do like this: |
| |
| void some_func(tabs) |
| { |
| INT32 i; |
| LPINT16 p = (LPINT16)tabs; |
| dbg_decl_str(listbox, 256); /* declare the string */ |
| |
| for (i = 0; i < descr->nb_tabs; i++) { |
| descr->tabs[i] = *p++<<1; |
| if(debugging_info(listbox)) /* write in it only if |
| dsprintf(listbox, "%hd ", descr->tabs[i]); /* we are gonna output it */ |
| } |
| dprintf_info(listbox, "Listbox %04x: settabstops %s\n", |
| wnd->hwndSelf, dbg_str(listbox)); /* output the whole thing */ |
| |
| dbg_reset_str(listbox); /* !!!reset the string!!! */ |
| for (i = 0; i < descr->extrainfo_nr; i++) { |
| descr->extrainfo = *p+1; |
| if(debugging_info(listbox)) /* write in it only if |
| dsprintf(listbox,"%3d ",descr->extrainfo); /* we are gonna output it */ |
| } |
| |
| dprintf_info(listbox, "Listbox %04x: extrainfo %s\n", |
| wnd->hwndSelf, dbg_str(listbox)); /* output the whole thing */ |
| |
| } |
| |
| IMPORTANT NOTE: |
| As I already stated, I do not think this will be the ultimate interface |
| for building in-memory debugging messages. In fact, I do have better ideas |
| which I hope to have time to implement for the next release. For this |
| reason, please try not to use it. However, if you need to output a line |
| in more than one dprintf_xxx calls, then USE THIS INTERFACE. DO NOT use |
| other methods. This way, I will easily translate everything to the new |
| interface (when it will become available). So, if you need to use if, |
| then follow the following guidelines: |
| -- wrap calls to dsprintf with a |
| if(debugging_yyy(xxx)) |
| dsprintf(xxx,...); |
| Of course, if the call to dsprintf is made from within a function |
| which you know is called only if debugging_yyy(xxx) is true |
| (say you call it only like this: |
| if(debugging_yyy(xxx)) |
| print_some_debug_info(); |
| ) |
| then you need not (and should not) wrap calls to dsprintf with |
| the before mentioned if. |
| -- name the string EXACTLY like the debugging channel on which |
| is going to be output. Please see the above example. |
| |
| |
| Resource identifiers |
| -------------------- |
| |
| Resource identifiers can be either strings or numbers. To make life a bit |
| easier for outputting this beasts (and to help you avoid the need to build |
| the message in memory), I introduced a new function called: |
| |
| debugres |
| |
| The function is defined in debugstr.h |
| and has the following prototype: |
| |
| LPSTR debugres(const void *id); |
| |
| It takes a pointer to the resource id and returns a nicely formatted |
| string of the identifier. |
| |
| It the high word of the pointer is 0, then it assumes that the |
| identifier is a number and thus returns a string of the form: |
| |
| #xxxx |
| |
| where xxxx are 4 hex-digits representing the low word of id. |
| |
| It the high word of the pointer is not 0, then it assumes that the |
| identifier is a string and thus returns a string of the form: |
| |
| '<identifier>' |
| |
| Thus, to use it, do something on the following lines: |
| |
| #include "debugstr.h" |
| |
| ... |
| |
| dprintf_yyy(xxx, "resource is %s", debugres(myresource)); |
| |
| |
| The -debugmsg command line option |
| --------------------------------- |
| |
| So, the -debugmsg command line option has been changed as follows: |
| - the new syntax is: -debugmsg [yyy]#xxx[,[yyy1]#xxx1]* |
| where # is either + or - |
| |
| - when the optional class argument (yyy) is not present, |
| then the statement will enable(+)/disable(-) all messages for |
| the given channel (xxx) on all classes. For example: |
| |
| -debugmsg +reg,-file |
| |
| enables all messages on the reg channel and disables all |
| messages on the file channel. |
| This is very close (actually identical) to the old semantics. |
| |
| - when the optional class argument (yyy) is present, |
| then the statement will enable(+)/disable(-) messages for |
| the given channel (xxx) only on the given class. For example: |
| |
| -debugmsg info+reg,warn-file |
| |
| enables info messages on the reg channel and disables warning |
| messages on the file channel. |
| |
| - also, the pseudo-channel all is also supported and it has the |
| intuitive semantics: |
| |
| -debugmsg +all -- enables all debug messages |
| -debugmsg -all -- disables all debug messages |
| -debugmsg yyy+all -- enables debug messages for class yyy on all |
| channels. |
| -debugmsg yyy-all -- disables debug messages for class yyy on all |
| channels. |
| |
| So, for example: |
| |
| -debugmsg warn-all -- disables all warning messages. |
| |
| |
| Also, note that at the moment: |
| - the fixme, err, warn classes are all enabled by default |
| - the info class is disabled by default |
| - there is no way to compile out the messages. All are |
| runtime configurable. This will come next release. |
| |
| |