1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
|
<chapter id="shared-files">
<title>Shared files</title>
<sect1 id="shared-files-intro">
<title>Introduction</title>
<para>
Here we provide functions that should be used by all parts of the program.
</para>
</sect1>
<sect1 id="report.h">
<title>report.h : Debugging and reporting</title>
<para>To enable the debug() function on all of the software, just type:
<screen>./configure --enable-debug and recompile with 'make'.</screen></para>
<procedure><title>Enabling the debug() function only in specific files:</title>
<step>
<para>Configure without enabling debug (that is without --enable-debug).</para>
</step>
<step>
<para>Edit the source file that you want to debug and put the following line
at the top, before the #include "report.h" line: <code>#define DEBUG</code>.
</para>
</step>
<step>
<para>Then recompile with 'make'.</para>
</step>
</procedure>
<para>
This way, the global DEBUG macro is off but is locally enabled in
certain parts of the software.</para>
<para>The reporting levels have the following meaning.</para>
<variablelist><title>Reporting Levels</title>
<varlistentry><term>0 RPT_CRIT</term>
<listitem><para>
Critical conditions: the program stops right after
this. Only use this if the program is actually exited
from the current function.
</para></listitem>
</varlistentry>
<varlistentry><term>1 RPT_ERR</term>
<listitem><para>
Error conditions: serious problem, program continues.
Use this just before you return -1 from a function.
</para></listitem>
</varlistentry>
<varlistentry><term>2 RPT_WARNING</term>
<listitem><para>
Warning conditions: Something that the user should
fix, but the program can continue without a real
problem. Ex: Protocol errors from a client.
</para></listitem>
</varlistentry>
<varlistentry><term>3 RPT_NOTICE</term>
<listitem><para>
Major event in the program: (un)loading of driver, client (dis)connect.
</para></listitem>
</varlistentry>
<varlistentry><term>4 RPT_INFO</term>
<listitem><para>
Minor event in the program: the activation of a
setting, details of a loaded driver, a key
reservation, a keypress, a screen switch.
</para></listitem>
</varlistentry>
<varlistentry><term>5 RPT_DEBUG</term>
<listitem><para>
Insignificant event: What function has been called, what subpart of a
function is being executed, what was received and sent
over the socket, etc.
</para></listitem>
</varlistentry>
</variablelist>
<para>Levels 4 (maybe) and 5 (certainly) should be reported using the debug
function. The code that this function generates will not be in the executable when
compiled without debugging. This way memory and CPU cycles are saved.</para>
<para>report.h file defines 3 functions for debugging and reporting:</para>
<sect2 id="set-reporting">
<title>Sets reporting level and message destination</title>
<funcsynopsis>
<funcprototype>
<funcdef>int <function>set_reporting</function></funcdef>
<paramdef>char * <parameter>application_name</parameter></paramdef>
<paramdef>int <parameter>new_level</parameter></paramdef>
<paramdef>int <parameter>new_dest</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
Returns <returnvalue>-1</returnvalue> on error or <returnvalue>0</returnvalue>
on success.
</para>
</sect2>
<sect2 id="report">
<title>Report the message to the selected destination if important enough</title>
<funcsynopsis>
<funcprototype>
<funcdef>void <function>report</function></funcdef>
<paramdef>const int <parameter>level</parameter></paramdef>
<paramdef>const char *<parameter>format</parameter></paramdef>
<paramdef>...</paramdef>
</funcprototype>
</funcsynopsis>
<para>Returns nothing (void).</para>
<para>The format parameter is the same as the one used by printf.</para>
</sect2>
<sect2 id="debug">
<title>Send debugging information if important enough</title>
<para>Consider the debug function to be exactly the same as the report function. The only difference is that it is only compiled in if DEBUG is defined.</para>
</sect2>
</sect1>
<sect1 id="LL.h">
<title>LL.h : Linked Lists (Doubly-Linked Lists)</title>
<sect2 id="LL.h-new">
<title>Creating a list</title>
<para>To create a list, do the following:</para>
<screen>
LinkedList *list;
list = LL_new();
if(!list) handle_an_error();
</screen>
<para>The list can hold any type of data. You will need to typecast your datatype to a "void *", though. So, to add something to the list, the following would be a good way to start:</para>
<screen>
typedef struct my_data {
char string[16];
int number;
} my_data;
my_data *thingie;
for(something to something else) {
thingie = malloc(sizeof(my_data));
LL_AddNode(list, (void *)thingie); // typecast it to a "void *"
}
</screen>
<para>For errors, the general convention is that "0" means success, and a negative number means failure. Check LL.c to be sure, though.</para>
</sect2>
<sect2 id="LL.h-edit">
<title>Changing data</title>
<para>To change the data, try this:</para>
<screen>
thingie = (my_data *)LL_Get(list); // typecast it back to "my_data"
thingie->number = another_number;
</screen>
<para>You don't need to "Put" the data back, but it doesn't hurt anything.</para>
<screen>
LL_Put(list, (void *)thingie);
</screen>
<para>However, if you want to point the node's data somewhere else, you'll need to get the current data first, keep track of it, then set the data to a new location:</para>
<screen>
my_data * old_thingie, new_thingie;
old_thingie = (my_data *)LL_Get(list);
LL_Put(list, (void *)new_thingie);
// Now, do something with old_thingie. (maybe, free it?)
</screen>
<para>Or, you could just delete the node entirely and then add a new one:</para>
<screen>
my_data * thingie;
thingie = (my_data *)LL_DeleteNode(list, NEXT);
free(thingie);
thingie->number = 666;
LL_InsertNode(list, (void *)thingie);
</screen>
</sect2>
<sect2 id="LL.h-iterate">
<title>Iterations throught the list</title>
<para>To iterate on each list item, try this:</para>
<screen>
LL_Rewind(list);
do {
my_data = (my_data *)LL_Get(list);
/* ... do something to it ... */
} while(LL_Next(list) == 0);
</screen>
</sect2>
<sect2 id="LL.h-stack">
<title>Using the list as a stack or a queue</title>
<para>You can also treat the list like a stack, or a queue. Just use the following functions:</para>
<screen>
LL_Push() // Regular stack stuff: add, remove, peek, rotate
LL_Pop()
LL_Top()
LL_Roll()
LL_Shift() // Other end of the stack (like in perl)
LL_Unshift()
LL_Look()
LL_UnRoll()
LL_Enqueue() // Standard queue operations
LL_Dequeue()
</screen>
<para>There are also other goodies, like sorting and searching.</para>
</sect2>
<sect2 id="LL.h-future">
<title>Future</title>
<para>Array-like operations will come later, to allow numerical indexing:</para>
<screen>
LL_nGet(list, 3);
LL_nSwap(list, 6, 13);
LL_nPut(list, -4, data); // Puts item at 4th place from the end..
</screen>
<para>More ideas for later:</para>
<screen>
LL_MoveNode(list, amount); // Slides a node to another spot in the list
-- LL_MoveNode(list, -1); // moves a node back one toward the head
</screen>
<para>That's about it, for now... Be sure to free the list when you're done!</para>
<para>See LL.c for more detailed descriptions of these functions.</para>
</sect2>
</sect1>
&make-driver;
</chapter>
|