we have a new homepage!
[privoxy.git] / doc / source / developer-manual.sgml
1 <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
2 <!--
3  File        :  $Source: /cvsroot/ijbswa/current/doc/source/developer-manual.sgml,v $
4
5  Purpose     :  developer manual
6                 This file belongs into
7                 ijbswa.sourceforge.net:/home/groups/i/ij/ijbswa/htdocs/
8                 
9  $Id: developer-manual.sgml,v 1.10 2002/03/24 12:33:01 swa Exp $
10
11  Written by and Copyright (C) 2001 the SourceForge
12  Privoxy team. http://www.privoxy.org/
13
14  Based on the Internet Junkbuster originally written
15  by and Copyright (C) 1997 Anonymous Coders and 
16  Junkbusters Corporation.  http://www.junkbusters.com
17 -->
18
19 <article id="index">
20   <artheader>
21     <title>Privoxy Developer Manual</title>
22
23     <pubdate>$Id: developer-manual.sgml,v 1.10 2002/03/24 12:33:01 swa Exp $</pubdate>
24
25     <authorgroup>
26       <author>
27         <affiliation>
28           <orgname>By: Privoxy Developers</orgname>
29         </affiliation>
30       </author>
31     </authorgroup>
32
33     <abstract>
34       <para>
35 The developer manual gives the users information on how to help the developer
36 team. It provides guidance on coding, testing, documentation and other
37 issues. <application>Privoxy</application> is a web proxy with advanced
38 filtering capabilities for protecting privacy, filtering web page content,
39 managing cookies, controlling access, and removing ads, banners, pop-ups and
40 other obnoxious Internet Junk. <application>Privoxy</application> has a very
41 flexible configuration and can be customized to suit individual needs and
42 tastes. <application>Privoxy</application> has application for both stand-alone
43 systems and multi-user networks.
44  </para>
45       <para>
46 You can find the latest version of the user manual at <ulink
47 url="http://www.privoxy.org/developer-manual/">http://www.privoxy.org/developer-manual/</ulink>.
48 Please see the Contact section in the user-manual if you want to contact the developers.
49  </para>
50
51 <!--        <para> -->
52 <!--    Feel free to send a note to the developers at <email>ijbswa-developers@lists.sourceforge.net</email>. -->
53 <!--   </para> -->
54
55     </abstract>
56   </artheader>
57
58   <!--   ~~~~~       New section      ~~~~~     -->
59   <sect1 id="introduction"><title>Introduction</title>
60     <para>To be filled.
61 </para>
62   </sect1>
63
64   <!--   ~~~~~       New section      ~~~~~     -->
65   <sect1 id="quickstart"><title>Quickstart to Privoxy Development</title>
66     <para>
67 You'll need an account on Sourceforge to support our development. Mail you ID
68 to the list and wait until a project manager has added you.
69
70 For the time beeing (read, this section is under construction), please note the
71 following guidelines for changing stuff in the code. If it is
72         <orderedlist numeration="arabic">
73                 <listitem><para>
74                 A bugfix / clean-up / cosmetic thing: shoot
75                 </para></listitem>
76                 <listitem><para>
77                 A new feature that can be turned off: shoot
78                 </para></listitem>
79                 <listitem><para>
80                 A clear improvement w/o side effects on other parts of the code: shoot
81                 </para></listitem>
82                 <listitem><para>
83                 A matter of taste: ask the list
84                 </para></listitem>
85                 <listitem><para>
86                 A major redesign of some part of the code: ask the list
87                 </para></listitem>
88         </orderedlist>  
89 </para>         
90   </sect1>      
91         
92   <!--   ~~~~~       New section      ~~~~~     -->
93   <sect1 id="documentation"><title>Documentation Guidelines</title>
94     <para>
95         All docs are in SGML format and located in the <computeroutput>doc/source</computeroutput> directory.
96         </para>
97         <para>
98         How do you update the webserver (i.e. the pages on sourceforge)?
99         <orderedlist numeration="arabic">
100                 <listitem><para>
101         Run <computeroutput>make dok</computeroutput> (which uses the documents in <computeroutput>doc/source</computeroutput> to update all
102         text files in <computeroutput>doc/text</computeroutput> and to update
103 all web documents in <computeroutput>doc/webserver</computeroutput>.
104                 </para></listitem>
105                 <listitem><para>
106         Run <computeroutput>make webserver</computeroutput> which copies all files from
107 <computeroutput>doc/webserver</computeroutput> to the sourceforge webserver
108 via scp.
109                 </para></listitem>
110         </orderedlist>
111   </para>
112  </sect1>
113
114 <!--     <listitem><para>be consistent with the redirect script (i.e. the <application>Privoxy</application> program -->
115 <!--       points via the redirect URL at sf to valid end-points in the document)</para></listitem> -->
116
117   <!--   ~~~~~       New section      ~~~~~     -->
118   <sect1 id="coding"><title>Coding Guidelines</title>
119
120     <sect2 id="s1"><title>Introduction</title>
121
122     <para>This set of standards is designed to make our lives easier.  It is
123     developed with the simple goal of helping us keep the "new and improved
124     <application>Privoxy</application>" consistent and reliable. Thus making
125     maintenance easier and increasing chances of success of the
126     project.</para>
127
128     <para>And that of course comes back to us as individuals. If we can
129     increase our development and product efficiencies then we can solve more
130     of the request for changes/improvements and in general feel good about
131     ourselves. ;-></para>
132
133   </sect2>
134
135     <sect2 id="s2"><title>Using Comments</title>
136  
137
138     <sect3 id="s3"><title>Comment, Comment, Comment</title>
139
140     <para><emphasis>Explanation:</emphasis></para>
141
142     <para>Comment as much as possible without commenting the obvious.
143     For example do not comment "aVariable is equal to bVariable".
144     Instead explain why aVariable should be equal to the bVariable.
145     Just because a person can read code does not mean they will
146     understand why or what is being done. A reader may spend a lot
147     more time figuring out what is going on when a simple comment
148     or explanation would have prevented the extra research. Please
149     help your brother IJB'ers out!</para>
150
151     <para>The comments will also help justify the intent of the code.
152     If the comment describes something different than what the code
153     is doing then maybe a programming error is occurring.</para>
154
155     <para><emphasis>Example:</emphasis></para>
156 <programlisting>
157 /* if page size greater than 1k ... */
158 if ( PageLength() > 1024 )
159 {
160     ... "block" the page up ...
161 }
162
163 /* if page size is small, send it in blocks */
164 if ( PageLength() > 1024 )
165 {
166     ... "block" the page up ...
167 }
168
169 This demonstrates 2 cases of "what not to do".  The first is a
170 "syntax comment".  The second is a comment that does not fit what
171 is actually being done.
172 </programlisting>
173   </sect3>
174
175     
176
177     <sect3 id="s4"><title>Use blocks for comments</title>
178
179     <para><emphasis>Explanation:</emphasis></para>
180
181     <para>Comments can help or they can clutter. They help when they
182     are differentiated from the code they describe. One line
183     comments do not offer effective separation between the comment
184     and the code. Block identifiers do, by surrounding the code
185     with a clear, definable pattern.</para>
186
187     <para><emphasis>Example:</emphasis></para>
188 <programlisting>
189 /*********************************************************************
190  * This will stand out clearly in your code!
191  *********************************************************************/
192 if ( thisVariable == thatVariable )
193 {
194    DoSomethingVeryImportant();
195 }
196
197
198 /* unfortunately, this may not */
199 if ( thisVariable == thatVariable )
200 {
201    DoSomethingVeryImportant();
202 }
203
204
205 if ( thisVariable == thatVariable ) /* this may not either */
206 {
207    DoSomethingVeryImportant();
208 }</programlisting>
209
210     <para><emphasis>Exception:</emphasis></para>
211
212     <para>If you are trying to add a small logic comment and do not
213     wish to "disrubt" the flow of the code, feel free to use a 1
214     line comment which is NOT on the same line as the code.</para>
215
216     
217   </sect3>
218     
219
220     <sect3 id="s5"><title>Keep Comments on their own line</title>
221
222     <para><emphasis>Explanation:</emphasis></para>
223
224     <para>It goes back to the question of readability. If the comment
225     is on the same line as the code it will be harder to read than
226     the comment that is on its own line.</para>
227
228     <para>There are three exceptions to this rule, which should be
229     violated freely and often: during the definition of variables,
230     at the end of closing braces, when used to comment
231     parameters.</para>
232
233     <para><emphasis>Example:</emphasis></para>
234 <programlisting>
235 /*********************************************************************
236  * This will stand out clearly in your code,
237  * But the second example won't.
238  *********************************************************************/
239 if ( thisVariable == thatVariable )
240 {
241    DoSomethingVeryImportant();
242 }
243
244 if ( thisVariable == thatVariable ) /*can you see me?*/
245 {
246    DoSomethingVeryImportant(); /*not easily*/
247 }
248
249
250 /*********************************************************************
251  * But, the encouraged exceptions:
252  *********************************************************************/
253 int urls_read     = 0;     /* # of urls read + rejected */
254 int urls_rejected = 0;     /* # of urls rejected */
255
256 if ( 1 == X )
257 {
258    DoSomethingVeryImportant();
259 }
260
261
262 short DoSomethingVeryImportant(
263    short firstparam,   /* represents something */
264    short nextparam     /* represents something else */ )
265 {
266    ...code here...
267
268 }   /* -END- DoSomethingVeryImportant */
269 </programlisting>
270   </sect3>
271     
272
273     <sect3 id="s6"><title>Comment each logical step</title>
274
275     <para><emphasis>Explanation:</emphasis></para>
276
277     <para>Logical steps should be commented to help others follow the
278     intent of the written code and comments will make the code more
279     readable.</para>
280
281     <para>If you have 25 lines of code without a comment, you should
282     probably go back into it to see where you forgot to put
283     one.</para>
284
285     <para>Most "for", "while", "do", etc... loops _probably_ need a
286     comment. After all, these are usually major logic
287     containers.</para>
288
289     
290   </sect3>
291     
292
293     <sect3 id="s7"><title>Comment All Functions Thoroughly</title>
294
295     <para><emphasis>Explanation:</emphasis></para>
296
297     <para>A reader of the code should be able to look at the comments
298     just prior to the beginning of a function and discern the
299     reason for its existence and the consequences of using it. The
300     reader should not have to read through the code to determine if
301     a given function is safe for a desired use. The proper
302     information thoroughly presented at the introduction of a
303     function not only saves time for subsequent maintenance or
304     debugging, it more importantly aids in code reuse by allowing a
305     user to determine the safety and applicability of any function
306     for the problem at hand. As a result of such benefits, all
307     functions should contain the information presented in the
308     addendum section of this document.</para>
309
310     
311   </sect3>
312     
313
314     <sect3 id="s8"><title>Comment at the end of braces if the
315     content is more than one screen length</title>
316
317     <para><emphasis>Explanation:</emphasis></para>
318
319     <para>Each closing brace should be followed on the same line by a
320     comment that describes the origination of the brace if the
321     original brace is off of the screen, or otherwise far away from
322     the closing brace. This will simplify the debugging,
323     maintenance, and readability of the code.</para>
324
325     <para>As a suggestion , use the following flags to make the
326     comment and its brace more readable:</para>
327
328     <para>use following a closing brace: } /* -END- if() or while ()
329     or etc... */</para>
330
331     <para><emphasis>Example:</emphasis></para>
332 <programlisting>
333 if ( 1 == X )
334 {
335    DoSomethingVeryImportant();
336    ...some long list of commands...
337 } /* -END- if x is 1 */
338
339 or:
340
341 if ( 1 == X )
342 {
343    DoSomethingVeryImportant();
344    ...some long list of commands...
345 } /* -END- if ( 1 == X ) */
346 </programlisting>
347   </sect3>
348     
349   </sect2>
350
351     <sect2 id="s9"><title>Naming Conventions</title>
352
353     
354
355     <sect3 id="s10"><title>Variable Names</title>
356
357     <para><emphasis>Explanation:</emphasis></para>
358
359     <para>Use all lowercase, and seperate words via an underscore
360     ('_'). Do not start an identifier with an underscore. (ANSI C
361     reserves these for use by the compiler and system headers.) Do
362     not use identifiers which are reserved in ANSI C++. (E.g.
363     template, class, true, false, ...). This is in case we ever
364     decide to port Privoxy to C++.</para>
365
366     <para><emphasis>Example:</emphasis></para>
367 <programlisting>
368 int ms_iis5_hack = 0;</programlisting>
369
370     <para><emphasis>Instead of:</emphasis></para>
371
372     <para>
373 <programlisting>
374 int msiis5hack = 0; int msIis5Hack = 0;
375 </programlisting>
376 </para>
377
378     
379
380   </sect3>    
381
382     <sect3 id="s11"><title>Function Names</title>
383
384     <para><emphasis>Explanation:</emphasis></para>
385
386     <para>Use all lowercase, and seperate words via an underscore
387     ('_'). Do not start an identifier with an underscore. (ANSI C
388     reserves these for use by the compiler and system headers.) Do
389     not use identifiers which are reserved in ANSI C++. (E.g.
390     template, class, true, false, ...). This is in case we ever
391     decide to port Privoxy to C++.</para>
392
393     <para><emphasis>Example:</emphasis></para>
394 <programlisting>
395 int load_some_file( struct client_state *csp )</programlisting>
396
397     <para><emphasis>Instead of:</emphasis></para>
398
399     <para>
400 <programlisting>
401 int loadsomefile( struct client_state *csp )
402 int loadSomeFile( struct client_state *csp )
403 </programlisting>
404 </para>
405
406     
407   </sect3>
408     
409
410     <sect3 id="s12"><title>Header file prototypes</title>
411
412     <para><emphasis>Explanation:</emphasis></para>
413
414     <para>Use a descriptive parameter name in the function prototype
415     in header files. Use the same parameter name in the header file
416     that you use in the c file.</para>
417
418     <para><emphasis>Example:</emphasis></para>
419 <programlisting>
420 (.h) extern int load_aclfile( struct client_state *csp );
421 (.c) int load_aclfile( struct client_state *csp )</programlisting>
422
423     <para><emphasis>Instead of:</emphasis>
424 <programlisting>
425 (.h) extern int load_aclfile( struct client_state * ); or 
426 (.h) extern int load_aclfile(); 
427 (.c) int load_aclfile( struct client_state *csp )
428 </programlisting>
429 </para>
430
431     
432   </sect3>
433     
434
435     <sect3 id="s13"><title>Enumerations, and #defines</title>
436
437     <para><emphasis>Explanation:</emphasis></para>
438
439     <para>Use all capital letters, with underscores between words. Do
440     not start an identifier with an underscore. (ANSI C reserves
441     these for use by the compiler and system headers.)</para>
442
443     <para><emphasis>Example:</emphasis></para>
444 <programlisting>
445 (enumeration) : enum Boolean { FALSE, TRUE };
446 (#define) : #define DEFAULT_SIZE 100;</programlisting>
447
448     <para><emphasis>Note:</emphasis> We have a standard naming scheme for #defines
449     that toggle a feature in the preprocessor: FEATURE_>, where
450     > is a short (preferably 1 or 2 word) description.</para>
451
452     <para><emphasis>Example:</emphasis></para>
453 <programlisting>
454 #define FEATURE_FORCE 1
455
456 #ifdef FEATURE_FORCE
457 #define FORCE_PREFIX blah
458 #endif /* def FEATURE_FORCE */
459 </programlisting>
460   </sect3>
461     
462
463     <sect3 id="s14"><title>Constants</title>
464
465     <para><emphasis>Explanation:</emphasis></para>
466
467     <para>Spell common words out entirely (do not remove vowels).</para>
468
469     <para>Use only widely-known domain acronyms and abbreviations.
470     Capitalize all letters of an acronym.</para>
471
472     <para>Use underscore (_) to separate adjacent acronyms and
473     abbreviations. Never terminate a name with an underscore.</para>
474
475     <para><emphasis>Example:</emphasis></para>
476 <programlisting>
477 #define USE_IMAGE_LIST 1</programlisting>
478
479     <para><emphasis>Instead of:</emphasis></para>
480
481     <para>
482 <programlisting>
483 #define USE_IMG_LST 1 or 
484 #define _USE_IMAGE_LIST 1 or
485 #define USE_IMAGE_LIST_ 1 or 
486 #define use_image_list 1 or
487 #define UseImageList 1
488 </programlisting>
489 </para>
490
491     
492   </sect3>
493
494   </sect2>
495     
496
497     <sect2 id="s15"><title>Using Space</title>
498
499     
500
501     <sect3 id="s16"><title>Put braces on a line by themselves.</title>
502
503     <para><emphasis>Explanation:</emphasis></para>
504
505     <para>The brace needs to be on a line all by itself, not at the
506     end of the statement. Curly braces should line up with the
507     construct that they're associated with. This practice makes it
508     easier to identify the opening and closing braces for a
509     block.</para>
510
511     <para><emphasis>Example:</emphasis></para>
512 <programlisting>
513 if ( this == that )
514 {
515    ...
516 }</programlisting>
517
518     <para><emphasis>Instead of:</emphasis></para>
519
520     <para>if ( this == that ) { ... }</para>
521
522     <para>or</para>
523
524     <para>if ( this == that ) { ... }</para>
525
526     <para><emphasis>Note:</emphasis> In the special case that the if-statement is
527     inside a loop, and it is trivial, i.e. it tests for a
528     condidtion that is obvious from the purpose of the block,
529     one-liners as above may optically preserve the loop structure
530     and make it easier to read.</para>
531
532     <para><emphasis>Status:</emphasis> developer-discrection.</para>
533
534     <para><emphasis>Example exception:</emphasis></para>
535 <programlisting>
536 while ( more lines are read )
537 {
538    /* Please document what is/is not a comment line here */
539    if ( it's a comment ) continue;
540
541    do_something( line );
542 }
543 </programlisting>
544   </sect3>
545     
546
547     <sect3 id="s17"><title>ALL control statements should have a
548     block</title>
549
550     <para><emphasis>Explanation:</emphasis></para>
551
552     <para>Using braces to make a block will make your code more
553     readable and less prone to error. All control statements should
554     have a block defined.</para>
555
556     <para><emphasis>Example:</emphasis></para>
557 <programlisting>
558 if ( this == that )
559 {
560    DoSomething();
561    DoSomethingElse();
562 }</programlisting>
563
564     <para><emphasis>Instead of:</emphasis></para>
565
566     <para>if ( this == that ) DoSomething(); DoSomethingElse();</para>
567
568     <para>or</para>
569
570     <para>if ( this == that ) DoSomething();</para>
571
572     <para><emphasis>Note:</emphasis> The first example in "Instead of" will execute
573     in a manner other than that which the developer desired (per
574     indentation). Using code braces would have prevented this
575     "feature". The "explanation" and "exception" from the point
576     above also applies.</para>
577
578     
579   </sect3>
580     
581
582     <sect3 id="s18"><title>Do not belabor/blow-up boolean
583     expressions</title>
584
585     <para><emphasis>Example:</emphasis></para>
586 <programlisting>
587 structure->flag = ( condition );</programlisting>
588
589     <para><emphasis>Instead of:</emphasis></para>
590
591     <para>if ( condition ) { structure->flag = 1; } else {
592     structure->flag = 0; }</para>
593
594     <para><emphasis>Note:</emphasis> The former is readable and consice. The later
595     is wordy and inefficient. Please assume that any developer new
596     to the project has at least a "good" knowledge of C/C++. (Hope
597     I do not offend by that last comment ... 8-)</para>
598
599     
600   </sect3>
601     
602
603     <sect3 id="s19"><title>Use white space freely because it is
604     free</title>
605
606     <para><emphasis>Explanation:</emphasis></para>
607
608     <para>Make it readable. The notable exception to using white space
609     freely is listed in the next guideline.</para>
610
611     <para><emphasis>Example:</emphasis></para>
612 <programlisting>
613 int firstValue   = 0;
614 int someValue    = 0;
615 int anotherValue = 0;
616 int thisVariable = 0;
617
618 if ( thisVariable == thatVariable )
619
620 firstValue = oldValue + ( ( someValue - anotherValue ) - whatever )
621 </programlisting>
622   </sect3>
623     
624
625     <sect3 id="s20"><title>Don't use white space around structure
626     operators</title>
627
628     <para><emphasis>Explanation:</emphasis></para>
629
630     <para>- structure pointer operator ( "->" ) - member operator (
631     "." ) - functions and parentheses</para>
632
633     <para>It is a general coding practice to put pointers, references,
634     and function parentheses next to names. With spaces, the
635     connection between the object and variable/function name is not
636     as clear.</para>
637
638     <para><emphasis>Example:</emphasis></para>
639 <programlisting>
640 aStruct->aMember;
641 aStruct.aMember;
642 FunctionName();</programlisting>
643
644     <para><emphasis>Instead of:</emphasis> aStruct -> aMember; aStruct . aMember;
645     FunctionName ();</para>
646
647     
648   </sect3>
649     
650
651     <sect3 id="s21"><title>Make the last brace of a function stand
652     out</title>
653
654     <para><emphasis>Example:</emphasis></para>
655 <programlisting>
656 int function1( ... )
657 {
658    ...code...
659    return( retCode );
660
661 }   /* -END- function1 */
662
663
664 int function2( ... )
665 {
666 }   /* -END- function2 */
667 </programlisting>
668
669     <para><emphasis>Instead of:</emphasis></para>
670
671     <para>int function1( ... ) { ...code... return( retCode ); } int
672     function2( ... ) { }</para>
673
674     <para><emphasis>Note:</emphasis> Use 1 blank line before the closing brace and 2
675     lines afterwards. This makes the end of function standout to
676     the most casual viewer. Although function comments help
677     seperate functions, this is still a good coding practice. In
678     fact, I follow these rules when using blocks in "for", "while",
679     "do" loops, and long if {} statements too. After all whitespace
680     is free!</para>
681
682     <para><emphasis>Status:</emphasis> developer-discrection on the number of blank
683     lines. Enforced is the end of function comments.</para>
684
685     
686   </sect3>
687     
688
689     <sect3 id="s22"><title>Use 3 character indentions</title>
690
691     <para><emphasis>Explanation:</emphasis></para>
692
693     <para>If some use 8 character TABs and some use 3 character TABs,
694     the code can look *very* ragged. So use 3 character indentions
695     only. If you like to use TABs, pass your code through a filter
696     such as "expand -t3" before checking in your code.</para>
697
698     <para><emphasis>Example:</emphasis></para>
699 <programlisting>
700 static const char * const url_code_map[256] =
701 {
702    NULL, ...
703 };
704
705
706 int function1( ... )
707 {
708    if ( 1 )
709    {
710       return( ALWAYS_TRUE );
711    }
712    else
713    {
714       return( HOW_DID_YOU_GET_HERE );
715    }
716
717    return( NEVER_GETS_HERE );
718
719 }
720 </programlisting>
721   </sect3>
722
723   </sect2>
724     
725
726     <sect2 id="s23"><title>Initializing</title>
727
728     
729
730     <sect3 id="s24"><title>Initialize all variables</title>
731
732     <para><emphasis>Explanation:</emphasis></para>
733
734     <para>Do not assume that the variables declared will not be used
735     until after they have been assigned a value somewhere else in
736     the code. Remove the chance of accidentally using an unassigned
737     variable.</para>
738
739     <para><emphasis>Example:</emphasis></para>
740 <programlisting>
741 short anShort = 0;
742 float aFloat  = 0;
743 struct *ptr = NULL;</programlisting>
744
745     <para><emphasis>Note:</emphasis> It is much easier to debug a SIGSEGV if the
746     message says you are trying to access memory address 00000000
747     and not 129FA012; or arrayPtr[20] causes a SIGSEV vs.
748     arrayPtr[0].</para>
749
750     <para><emphasis>Status:</emphasis> developer-discrection if and only if the
751     variable is assigned a value "shortly after" declaration.</para>
752
753   </sect3>
754   </sect2>
755     
756
757     <sect2 id="s25"><title>Functions</title>
758
759     
760
761     <sect3 id="s26"><title>Name functions that return a boolean as a
762     question.</title>
763
764     <para><emphasis>Explanation:</emphasis></para>
765
766     <para>Value should be phrased as a question that would logically
767     be answered as a true or false statement</para>
768
769     <para><emphasis>Example:</emphasis></para>
770 <programlisting>
771 ShouldWeBlockThis();
772 ContainsAnImage();
773 IsWebPageBlank();
774 </programlisting>
775   </sect3>
776     
777
778     <sect3 id="s27"><title>Always specify a return type for a
779     function.</title>
780
781     <para><emphasis>Explanation:</emphasis></para>
782
783     <para>The default return for a function is an int. To avoid
784     ambiguity, create a return for a function when the return has a
785     purpose, and create a void return type if the function does not
786     need to return anything.</para>
787
788     
789   </sect3>
790     
791
792     <sect3 id="s28"><title>Minimize function calls when iterating by
793     using variables</title>
794
795     <para><emphasis>Explanation:</emphasis></para>
796
797     <para>It is easy to write the following code, and a clear argument
798     can be made that the code is easy to understand:</para>
799
800     <para><emphasis>Example:</emphasis></para>
801 <programlisting>
802 for ( size_t cnt = 0; cnt &lt; blockListLength(); cnt ++ )
803 {
804    ....
805 }</programlisting>
806
807     <para><emphasis>Note:</emphasis> Unfortunately, this makes a function call for
808     each and every iteration. This increases the overhead in the
809     program, because the compiler has to look up the function each
810     time, call it, and return a value. Depending on what occurs in
811     the blockListLength() call, it might even be creating and
812     destroying structures with each iteration, even though in each
813     case it is comparing "cnt" to the same value, over and over.
814     Remember too - even a call to blockListLength() is a function
815     call, with the same overhead.</para>
816
817     <para>Instead of using a function call during the iterations,
818     assign the value to a variable, and evaluate using the
819     variable.</para>
820
821     <para><emphasis>Example:</emphasis></para>
822 <programlisting>
823 size_t len = blockListLength();
824
825 for ( size_t cnt = 0; cnt &lt; len; cnt ++ )
826 {
827    ....
828 }</programlisting>
829
830     <para><emphasis>Exceptions:</emphasis> if the value of blockListLength() *may*
831     change or could *potentially* change, then you must code the
832     function call in the for/while loop.</para>
833
834     
835   </sect3>
836     
837
838     <sect3 id="s29"><title>Pass and Return by Const Reference</title>
839
840     <para><emphasis>Explanation:</emphasis></para>
841
842     <para>This allows a developer to define a const pointer and call
843     your function. If your function does not have the const
844     keyword, we may not be able to use your function. Consider
845     strcmp, if it were defined as: extern int strcmp( char *s1,
846     char *s2 );</para>
847
848     <para>I could then not use it to compare argv's in main: int main(
849     int argc, const char *argv[] ) { strcmp( argv[0], "privoxy"
850     ); }</para>
851
852     <para>Both these pointers are *const*! If the c runtime library
853     maintainers do it, we should too.</para>
854
855     
856   </sect3>
857     
858
859     <sect3 id="s30"><title>Pass and Return by Value</title>
860
861     <para><emphasis>Explanation:</emphasis></para>
862
863     <para>Most structures cannot fit onto a normal stack entry (i.e.
864     they are not 4 bytes or less). Aka, a function declaration
865     like: int load_aclfile( struct client_state csp )</para>
866
867     <para>would not work. So, to be consistent, we should declare all
868     prototypes with "pass by value": int load_aclfile( struct
869     client_state *csp )</para>
870
871     
872   </sect3>
873     
874
875     <sect3 id="s31"><title>Names of include files</title>
876
877     <para><emphasis>Explanation:</emphasis></para>
878
879     <para>Your include statements should contain the file name without
880     a path. The path should be listed in the Makefile, using -I as
881     processor directive to search the indicated paths. An exception
882     to this would be for some proprietary software that utilizes a
883     partial path to distinguish their header files from system or
884     other header files.</para>
885
886     <para><emphasis>Example:</emphasis></para>
887 <programlisting>
888 #include &lt;iostream.h&gt;     /* This is not a local include */
889 #include "config.h"       /* This IS a local include */
890 </programlisting>
891
892     <para><emphasis>Exception:</emphasis></para>
893
894     <para>
895 <programlisting>
896 /* This is not a local include, but requires a path element. */ 
897 #include &lt;sys/fileName.h&gt;
898 </programlisting>
899 </para>
900
901     <para><emphasis>Note:</emphasis> Please! do not add "-I." to the Makefile
902     without a _very_ good reason. This duplicates the #include
903     "file.h" behaviour.</para>
904
905     
906   </sect3>
907     
908
909     <sect3 id="s32"><title>Provide multiple inclusion
910     protection</title>
911
912     <para><emphasis>Explanation:</emphasis></para>
913
914     <para>Prevents compiler and linker errors resulting from
915     redefinition of items.</para>
916
917     <para>Wrap each header file with the following syntax to prevent
918     multiple inclusions of the file. Of course, replace PROJECT_H
919     with your file name, with "." Changed to "_", and make it
920     uppercase.</para>
921
922     <para><emphasis>Example:</emphasis></para>
923 <programlisting>
924 #ifndef PROJECT_H_INCLUDED
925 #define PROJECT_H_INCLUDED
926  ...
927 #endif /* ndef PROJECT_H_INCLUDED */
928 </programlisting>
929   </sect3>
930     
931
932     <sect3 id="s33"><title>Use `extern "C"` when appropriate</title>
933
934     <para><emphasis>Explanation:</emphasis></para>
935
936     <para>If our headers are included from C++, they must declare our
937     functions as `extern "C"`. This has no cost in C, but increases
938     the potential re-usability of our code.</para>
939
940     <para><emphasis>Example:</emphasis></para>
941 <programlisting>
942 #ifdef __cplusplus
943 extern "C"
944 {
945 #endif /* def __cplusplus */
946
947 ... function definitions here ...
948
949 #ifdef __cplusplus
950 }
951 #endif /* def __cplusplus */
952 </programlisting>
953   </sect3>
954     
955
956     <sect3 id="s34"><title>Where Possible, Use Forward Struct
957     Declaration Instead of Includes</title>
958
959     <para><emphasis>Explanation:</emphasis></para>
960
961     <para>Useful in headers that include pointers to other struct's.
962     Modifications to excess header files may cause needless
963     compiles.</para>
964
965     <para><emphasis>Example:</emphasis></para>
966 <programlisting>
967 /*********************************************************************
968  * We're avoiding an include statement here!
969  *********************************************************************/
970 struct file_list;
971 extern file_list *xyz;</programlisting>
972
973     <para><emphasis>Note:</emphasis> If you declare "file_list xyz;" (without the
974     pointer), then including the proper header file is necessary.
975     If you only want to prototype a pointer, however, the header
976     file is unneccessary.</para>
977
978     <para><emphasis>Status:</emphasis> Use with discrection.</para>
979
980     
981   </sect3>
982   </sect2>
983
984     <sect2 id="s35"><title>General Coding Practices</title>
985
986     
987
988     <sect3 id="s36"><title>Turn on warnings</title>
989
990     <para><emphasis>Explanation</emphasis></para>
991
992     <para>Compiler warnings are meant to help you find bugs. You
993     should turn on as many as possible. With GCC, the switch is
994     "-Wall". Try and fix as many warnings as possible.</para>
995
996     
997   </sect3>
998     
999
1000     <sect3 id="s37"><title>Provide a default case for all switch
1001     statements</title>
1002
1003     <para><emphasis>Explanation:</emphasis></para>
1004
1005     <para>What you think is guaranteed is never really guaranteed. The
1006     value that you don't think you need to check is the one that
1007     someday will be passed. So, to protect yourself from the
1008     unknown, always have a default step in a switch statement.</para>
1009
1010     <para><emphasis>Example:</emphasis></para>
1011 <programlisting>
1012 switch( hash_string( cmd ) )
1013 {
1014    case hash_actions_file :
1015       ... code ...
1016       break;
1017
1018    case hash_confdir :
1019       ... code ...
1020       break;
1021
1022    default :
1023       log_error( ... );
1024       ... anomly code goes here ...
1025       continue; / break; / exit( 1 ); / etc ...
1026
1027 } /* end switch( hash_string( cmd ) ) */</programlisting>
1028
1029     <para><emphasis>Note:</emphasis> If you already have a default condition, you
1030     are obviously exempt from this point. Of note, most of the
1031     WIN32 code calls `DefWindowProc' after the switch statement.
1032     This API call *should* be included in a default statement.</para>
1033
1034     <para><emphasis>Another Note:</emphasis> This is not so much a readability issue
1035     as a robust programming issue. The "anomly code goes here" may
1036     be no more than a print to the STDERR stream (as in
1037     load_config). Or it may really be an ABEND condition.</para>
1038
1039     <para><emphasis>Status:</emphasis> Programmer discretion is advised.</para>
1040
1041     
1042   </sect3>
1043     
1044
1045     <sect3 id="s38"><title>Try to avoid falling through cases in a
1046     switch statement.</title>
1047
1048     <para><emphasis>Explanation:</emphasis></para>
1049
1050     <para>In general, you will want to have a 'break' statement within
1051     each 'case' of a switch statement. This allows for the code to
1052     be more readable and understandable, and furthermore can
1053     prevent unwanted surprises if someone else later gets creative
1054     and moves the code around.</para>
1055
1056     <para>The language allows you to plan the fall through from one
1057     case statement to another simply by omitting the break
1058     statement within the case statement. This feature does have
1059     benefits, but should only be used in rare cases. In general,
1060     use a break statement for each case statement.</para>
1061
1062     <para>If you choose to allow fall through, you should comment both
1063     the fact of the fall through and reason why you felt it was
1064     necessary.</para>
1065
1066     
1067   </sect3>
1068     
1069
1070     <sect3 id="s39"><title>Use 'long' or 'short' Instead of
1071     'int'</title>
1072
1073     <para><emphasis>Explanation:</emphasis></para>
1074
1075     <para>On 32-bit platforms, int usually has the range of long. On
1076     16-bit platforms, int has the range of short.</para>
1077
1078     <para><emphasis>Status:</emphasis> open-to-debate. In the case of most FSF
1079     projects (including X/GNU-Emacs), there are typedefs to int4,
1080     int8, int16, (or equivalence ... I forget the exact typedefs
1081     now). Should we add these to IJB now that we have a "configure"
1082     script?</para>
1083
1084     
1085   </sect3>
1086     
1087
1088     <sect3 id="s40"><title>Don't mix size_t and other types</title>
1089
1090     <para><emphasis>Explanation:</emphasis></para>
1091
1092     <para>The type of size_t varies across platforms. Do not make
1093     assumptions about whether it is signed or unsigned, or about
1094     how long it is. Do not compare a size_t against another
1095     variable of a different type (or even against a constant)
1096     without casting one of the values. Try to avoid using size_t if
1097     you can.</para>
1098
1099     
1100   </sect3>
1101     
1102
1103     <sect3 id="s41"><title>Declare each variable and struct on its
1104     own line.</title>
1105
1106     <para><emphasis>Explanation:</emphasis></para>
1107
1108     <para>It can be tempting to declare a series of variables all on
1109     one line. Don't.</para>
1110
1111     <para><emphasis>Example:</emphasis></para>
1112 <programlisting>
1113 long a = 0;
1114 long b = 0;
1115 long c = 0;</programlisting>
1116
1117     <para><emphasis>Instead of:</emphasis></para>
1118
1119     <para>long a, b, c;</para>
1120
1121     <para><emphasis>Explanation:</emphasis> - there is more room for comments on the
1122     individual variables - easier to add new variables without
1123     messing up the original ones - when searching on a variable to
1124     find its type, there is less clutter to "visually"
1125     eliminate</para>
1126
1127     <para><emphasis>Exceptions:</emphasis> when you want to declare a bunch of loop
1128     variables or other trivial variables; feel free to declare them
1129     on 1 line. You should, although, provide a good comment on
1130     their functions.</para>
1131
1132     <para><emphasis>Status:</emphasis> developer-discrection.</para>
1133
1134     
1135   </sect3>
1136     
1137
1138     <sect3 id="s42"><title>Use malloc/zalloc sparingly</title>
1139
1140     <para><emphasis>Explanation:</emphasis></para>
1141
1142     <para>Create a local stuct (on the stack) if the variable will
1143     live and die within the context of one function call.</para>
1144
1145     <para>Only "malloc" a struct (on the heap) if the variable's life
1146     will extend beyond the context of one function call.</para>
1147
1148     <para><emphasis>Example:</emphasis></para>
1149 <programlisting>
1150 If a function creates a struct and stores a pointer to it in a
1151 list, then it should definately be allocated via `malloc'.
1152 </programlisting>
1153   </sect3>
1154     
1155
1156     <sect3 id="s43"><title>The Programmer Who Uses 'malloc' is
1157     Responsible for Ensuring 'free'</title>
1158
1159     <para><emphasis>Explanation:</emphasis></para>
1160
1161     <para>If you have to "malloc" an instance, you are responsible for
1162     insuring that the instance is `free'd, even if the deallocation
1163     event falls within some other programmer's code. You are also
1164     responsible for ensuring that deletion is timely (i.e. not too
1165     soon, not too late). This is known as "low-coupling" and is a
1166     "good thing (tm)". You may need to offer a
1167     free/unload/destuctor type function to accomodate this.</para>
1168
1169     <para><emphasis>Example:</emphasis></para>
1170 <programlisting>
1171 int load_re_filterfile( struct client_state *csp ) { ... }
1172 static void unload_re_filterfile( void *f ) { ... }</programlisting>
1173
1174     <para><emphasis>Exceptions:</emphasis></para>
1175
1176     <para>The developer cannot be expected to provide `free'ing
1177     functions for C run-time library functions ... such as
1178     `strdup'.</para>
1179
1180     <para><emphasis>Status:</emphasis> developer-discrection. The "main" use of this
1181     standard is for allocating and freeing data structures (complex
1182     or nested).</para>
1183
1184     
1185   </sect3>
1186     
1187
1188     <sect3 id="s44"><title>Add loaders to the `file_list' structure
1189     and in order</title>
1190
1191     <para><emphasis>Explanation:</emphasis></para>
1192
1193     <para>I have ordered all of the "blocker" file code to be in alpha
1194     order. It is easier to add/read new blockers when you expect a
1195     certain order.</para>
1196
1197     <para><emphasis>Note:</emphasis> It may appear that the alpha order is broken in
1198     places by POPUP tests coming before PCRS tests. But since
1199     POPUPs can also be referred to as KILLPOPUPs, it is clear that
1200     it should come first.</para>
1201
1202     
1203   </sect3>
1204     
1205
1206     <sect3 id="s45"><title>"Uncertain" new code and/or changes to
1207     exitinst code, use FIXME</title>
1208
1209     <para><emphasis>Explanation:</emphasis></para>
1210
1211     <para>If you have enough confidence in new code or confidence in
1212     your changes, but are not *quite* sure of the reprocussions,
1213     add this:</para>
1214
1215     <para>/* FIXME: this code has a logic error on platform XYZ, *
1216     attempthing to fix */ #ifdef PLATFORM ...changed code here...
1217     #endif</para>
1218
1219     <para>or:</para>
1220
1221     <para>/* FIXME: I think the original author really meant this...
1222     */ ...changed code here...</para>
1223
1224     <para>or:</para>
1225
1226     <para>/* FIXME: new code that *may* break something else... */
1227     ...new code here...</para>
1228
1229     <para><emphasis>Note:</emphasis> If you make it clear that this may or may not
1230     be a "good thing (tm)", it will be easier to identify and
1231     include in the project (or conversly exclude from the
1232     project).</para>
1233
1234     
1235   </sect3>
1236
1237   </sect2>
1238
1239     <sect2 id="s46"><title>Addendum: Template for files and function
1240     comment blocks:</title>
1241
1242     <para><emphasis>Example for file comments:</emphasis></para>
1243 <programlisting>
1244 const char FILENAME_rcs[] = "$Id: developer-manual.sgml,v 1.10 2002/03/24 12:33:01 swa Exp $";
1245 /*********************************************************************
1246  *
1247  * File        :  $S<!-- Break CVS Substitution -->ource$
1248  *
1249  * Purpose     :  (Fill me in with a good description!)
1250  *
1251  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
1252  *                Privoxy team. http://www.privoxy.org/
1253  *
1254  *                Based on the Internet Junkbuster originally written
1255  *                by and Copyright (C) 1997 Anonymous Coders and
1256  *                Junkbusters Corporation.  http://www.junkbusters.com
1257  *
1258  *                This program is free software; you can redistribute it
1259  *                and/or modify it under the terms of the GNU General
1260  *                Public License as published by the Free Software
1261  *                Foundation; either version 2 of the License, or (at
1262  *                your option) any later version.
1263  *
1264  *                This program is distributed in the hope that it will
1265  *                be useful, but WITHOUT ANY WARRANTY; without even the
1266  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
1267  *                PARTICULAR PURPOSE.  See the GNU General Public
1268  *                License for more details.
1269  *
1270  *                The GNU General Public License should be included with
1271  *                this file.  If not, you can view it at
1272  *                http://www.gnu.org/copyleft/gpl.html
1273  *                or write to the Free Software Foundation, Inc., 59
1274  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
1275  *
1276  * Revisions   :
1277  *    $L<!-- Break CVS Substitution -->og$
1278  *
1279  *********************************************************************/
1280
1281
1282 #include "config.h"
1283
1284    ...necessary include files for us to do our work...
1285
1286 const char FILENAME_h_rcs[] = FILENAME_H_VERSION;
1287 </programlisting>
1288
1289     <para><emphasis>Note:</emphasis> This declares the rcs variables that should be
1290     added to the "show-proxy-args" page. If this is a brand new
1291     creation by you, you are free to change the "Copyright" section
1292     to represent the rights you wish to maintain.</para>
1293
1294     <para><emphasis>Note:</emphasis> The formfeed character that is present right
1295     after the comment flower box is handy for (X|GNU)Emacs users to
1296     skip the verbige and get to the heart of the code (via
1297     `forward-page' and `backward-page'). Please include it if you
1298     can.</para>
1299
1300     <para><emphasis>Example for file header comments:</emphasis></para>
1301 <programlisting>
1302 #ifndef _FILENAME_H
1303 #define _FILENAME_H
1304 #define FILENAME_H_VERSION "$Id: developer-manual.sgml,v 1.10 2002/03/24 12:33:01 swa Exp $"
1305 /*********************************************************************
1306  *
1307  * File        :  $S<!-- Break CVS Substitution -->ource$
1308  *
1309  * Purpose     :  (Fill me in with a good description!)
1310  *
1311  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
1312  *                Privoxy team. http://www.privoxy.org/
1313  *
1314  *                Based on the Internet Junkbuster originally written
1315  *                by and Copyright (C) 1997 Anonymous Coders and
1316  *                Junkbusters Corporation.  http://www.junkbusters.com
1317  *
1318  *                This program is free software; you can redistribute it
1319  *                and/or modify it under the terms of the GNU General
1320  *                Public License as published by the Free Software
1321  *                Foundation; either version 2 of the License, or (at
1322  *                your option) any later version.
1323  *
1324  *                This program is distributed in the hope that it will
1325  *                be useful, but WITHOUT ANY WARRANTY; without even the
1326  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
1327  *                PARTICULAR PURPOSE.  See the GNU General Public
1328  *                License for more details.
1329  *
1330  *                The GNU General Public License should be included with
1331  *                this file.  If not, you can view it at
1332  *                http://www.gnu.org/copyleft/gpl.html
1333  *                or write to the Free Software Foundation, Inc., 59
1334  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
1335  *
1336  * Revisions   :
1337  *    $L<!-- Break CVS Substitution -->og$
1338  *
1339  *********************************************************************/
1340
1341
1342 #include "project.h"
1343
1344 #ifdef __cplusplus
1345 extern "C" {
1346 #endif
1347
1348    ... function headers here ...
1349
1350
1351 /* Revision control strings from this header and associated .c file */
1352 extern const char FILENAME_rcs[];
1353 extern const char FILENAME_h_rcs[];
1354
1355
1356 #ifdef __cplusplus
1357 } /* extern "C" */
1358 #endif
1359
1360 #endif /* ndef _FILENAME_H */
1361
1362 /*
1363   Local Variables:
1364   tab-width: 3
1365   end:
1366 */
1367 </programlisting>
1368
1369     <para><emphasis>Example for function comments:</emphasis></para>
1370 <programlisting>
1371 /*********************************************************************
1372  *
1373  * Function    :  FUNCTION_NAME
1374  *
1375  * Description :  (Fill me in with a good description!)
1376  *
1377  * parameters  :
1378  *          1  :  param1 = pointer to an important thing
1379  *          2  :  x      = pointer to something else
1380  *
1381  * Returns     :  0 => Ok, everything else is an error.
1382  *
1383  *********************************************************************/
1384 int FUNCTION_NAME( void *param1, const char *x )
1385 {
1386    ...
1387    return( 0 );
1388
1389 }
1390 </programlisting>
1391
1392     <para><emphasis>Note:</emphasis> If we all follow this practice, we should be
1393     able to parse our code to create a "self-documenting" web
1394     page.</para>
1395
1396   </sect2>
1397
1398   </sect1>
1399
1400   <!--   ~~~~~       New section      ~~~~~     -->
1401   <sect1 id="cvs"><title>Version Control Guidelines</title>
1402     <para>To be filled. note on cvs comments. don't comment what you did, comment
1403 why you did it.
1404 </para>
1405   </sect1>
1406
1407   <!--   ~~~~~       New section      ~~~~~     -->
1408   <sect1 id="testing"><title>Testing Guidelines</title>
1409     <para>To be filled.
1410 </para>
1411
1412     <!--   ~~~~~       New section      ~~~~~     -->
1413     <sect2 id="testing-plan"><title>Testplan for releases</title>
1414       <para>
1415 Explain release numbers. major, minor. developer releases. etc.
1416
1417 <orderedlist numeration="arabic">
1418           <listitem><para>
1419 Remove any existing rpm with rpm -e
1420 </para></listitem>
1421           <listitem><para>
1422 Remove any file that was left over. This includes (but is not limited to)
1423       <itemizedlist>
1424                 <listitem><para>/var/log/privoxy</para></listitem>
1425                 <listitem><para>/etc/privoxy</para></listitem>
1426                 <listitem><para>/usr/sbin/privoxy</para></listitem>
1427                 <listitem><para>/etc/init.d/privoxy</para></listitem>
1428                 <listitem><para>/usr/doc/privoxy*</para></listitem>
1429               </itemizedlist>
1430 </para></listitem>
1431           <listitem><para>
1432 Install the rpm. Any error messages?
1433 </para></listitem>
1434           <listitem><para>start,stop,status <application>Privoxy</application> with the specific script
1435       (e.g. /etc/rc.d/init/privoxy stop). Reboot your machine. Does
1436       autostart work?</para></listitem>
1437           <listitem><para>Start browsing. Does <application>Privoxy</application> work? Logfile written?</para></listitem>
1438           <listitem><para>Remove the rpm. Any error messages? All files removed?</para></listitem>
1439         </orderedlist>
1440 </para>
1441     </sect2>
1442
1443     <!--   ~~~~~       New section      ~~~~~     -->
1444     <sect2 id="testing-report"><title>Test reports</title>
1445       <para>
1446 Please submit test reports only with the <ulink url="http://sourceforge.net/tracker/?func=add&amp;group_id=11118&amp;atid=395005">test form</ulink>
1447 at sourceforge. Three simple steps:
1448         <itemizedlist>
1449           
1450           <listitem><para>Select category: the distribution you test on.</para></listitem>
1451           <listitem><para>Select group: the version of <application>Privoxy</application> that we are about to release.</para></listitem>
1452           <listitem><para>Fill the Summary and Detailed Description with something
1453               intelligent (keep it short and precise).</para>
1454           </listitem>
1455         </itemizedlist>
1456         Do not mail to the mailinglist (we cannot keep track on issues there).
1457       </para>
1458     </sect2>
1459     
1460   </sect1>
1461   
1462   <!--   ~~~~~       New section      ~~~~~     -->
1463   <sect1 id="contact"><title>Contact the developers</title>
1464     <para>Please see the user manual for information on how to contact the developers.
1465     </para>
1466   </sect1>
1467   
1468   <!--   ~~~~~       New section      ~~~~~     -->
1469   <sect1 id="copyright"><title>Copyright and History</title>
1470     <para>Please see the user manual for information on Copyright and History.
1471     </para>
1472   </sect1>
1473   
1474   <!--   ~~~~~       New section      ~~~~~     -->
1475   <sect1 id="seealso"><title>See also</title>
1476     <para>Please see the user manual for information on references.
1477     </para>
1478   </sect1>
1479
1480   <!--
1481
1482   This program is free software; you can redistribute it 
1483   and/or modify it under the terms of the GNU General
1484   Public License as published by the Free Software
1485   Foundation; either version 2 of the License, or (at
1486   your option) any later version.
1487
1488   This program is distributed in the hope that it will
1489   be useful, but WITHOUT ANY WARRANTY; without even the
1490   implied warranty of MERCHANTABILITY or FITNESS FOR A
1491   PARTICULAR PURPOSE.  See the GNU General Public
1492   License for more details.
1493
1494   The GNU General Public License should be included with
1495   this file.  If not, you can view it at
1496   http://www.gnu.org/copyleft/gpl.html
1497   or write to the Free Software Foundation, Inc., 59
1498   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
1499
1500   $Log: developer-manual.sgml,v $
1501   Revision 1.10  2002/03/24 12:33:01  swa
1502   more additions.
1503
1504   Revision 1.9  2002/03/24 11:01:05  swa
1505   name change
1506
1507   Revision 1.8  2002/03/23 15:13:11  swa
1508   renamed every reference to the old name with foobar.
1509   fixed "application foobar application" tag, fixed
1510   "the foobar" with "foobar". left junkbustser in cvs
1511   comments and remarks to history untouched.
1512
1513   Revision 1.7  2002/03/11 13:13:27  swa
1514   correct feedback channels
1515
1516   Revision 1.6  2002/02/24 14:25:06  jongfoster
1517   Formatting changes.  Now changing the doctype to DocBook XML 4.1
1518   will work - no other changes are needed.
1519
1520   Revision 1.5  2001/10/31 18:16:51  swa
1521   documentation added: howto generate docs in text and html
1522   format, howto move stuff to the webserver.
1523
1524   Revision 1.4  2001/09/23 10:13:48  swa
1525   upload process established. run make webserver and
1526   the documentation is moved to the webserver. documents
1527   are now linked correctly.
1528
1529   Revision 1.3  2001/09/13 15:27:40  swa
1530   cosmetics
1531
1532   Revision 1.2  2001/09/13 15:20:17  swa
1533   merged standards into developer manual
1534
1535   Revision 1.1  2001/09/12 15:36:41  swa
1536   source files for junkbuster documentation
1537
1538   Revision 1.3  2001/09/10 17:43:59  swa
1539   first proposal of a structure.
1540
1541   Revision 1.2  2001/06/13 14:28:31  swa
1542   docs should have an author.
1543
1544   Revision 1.1  2001/06/13 14:20:37  swa
1545   first import of project's documentation for the webserver.
1546
1547   -->
1548
1549 </article>