more single file to be included at multiple points. make maintaining easier
[privoxy.git] / doc / source / developer-manual.sgml
1 <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[
2 <!entity % dummy "INCLUDE"> 
3 <!entity supported SYSTEM "supported.sgml">
4 <!entity newfeatures SYSTEM "newfeatures.sgml">
5 <!entity p-intro SYSTEM "privoxy.sgml">
6 <!entity history SYSTEM "history.sgml">
7 <!entity seealso SYSTEM "seealso.sgml">
8 <!entity contacting SYSTEM "contacting.sgml">
9 <!entity copyright SYSTEM "copyright.sgml">
10 <!entity p-version "2.9.13">
11 <!entity p-status "BETA">
12 <!entity % p-not-stable "INCLUDE"> <!-- set to IGNORE for stable release  -->
13 <!entity % p-stable "IGNORE">      <!-- set INCLUDE for stable release    -->
14 <!entity % p-text "IGNORE">        <!-- define we are not a text only doc -->
15 <!entity % p-doc "INCLUDE">        <!-- and we are a formal doc           -->
16 ]>
17 <!--
18  File        :  $Source: /cvsroot/ijbswa/current/doc/source/developer-manual.sgml,v $
19
20  Purpose     :  developer manual
21                 This file belongs into
22                 ijbswa.sourceforge.net:/home/groups/i/ij/ijbswa/htdocs/
23                 
24  $Id: developer-manual.sgml,v 1.21 2002/04/04 06:48:37 hal9 Exp $
25
26  Written by and Copyright (C) 2001 the SourceForge
27  Privoxy team. http://www.privoxy.org/
28
29  Based on the Internet Junkbuster originally written
30  by and Copyright (C) 1997 Anonymous Coders and 
31  Junkbusters Corporation.  http://www.junkbusters.com
32 -->
33
34 <article id="index">
35   <artheader>
36     <title>Privoxy Developer Manual</title>
37
38     <pubdate>$Id: developer-manual.sgml,v 1.21 2002/04/04 06:48:37 hal9 Exp $</pubdate>
39
40     <authorgroup>
41       <author>
42         <affiliation>
43           <orgname>By: Privoxy Developers</orgname>
44         </affiliation>
45       </author>
46     </authorgroup>
47
48     <abstract>
49 <![%dummy;[
50  <para>
51  <comment>
52   This is here to keep vim syntax file from breaking :/
53   If I knew enough to fix it, I would.
54   PLEASE DO NOT REMOVE! HB: hal@foobox.net
55  </comment>
56  </para>
57  ]]>
58 <para>
59  The developer manual gives the users information on how to help the developer
60  team. It provides guidance on coding, testing, documentation and other
61  issues. 
62  </para>
63
64 <!-- Include privoxy.sgml boilerplate text: -->
65
66  &p-intro;
67
68 <!-- end boilerplate -->
69
70 <para>
71  You can find the latest version of the this manual at <ulink
72  url="http://www.privoxy.org/developer-manual/">http://www.privoxy.org/developer-manual/</ulink>.
73  Please see the Contact section of the <ulink
74  url="../user-manual/contact.html">User Manual</ulink> on how to contact the
75  developers.
76 </para>
77
78 <!--        <para> -->
79 <!--    Feel free to send a note to the developers at <email>ijbswa-developers@lists.sourceforge.net</email>. -->
80 <!--   </para> -->
81
82     </abstract>
83   </artheader>
84
85   <!--   ~~~~~       New section      ~~~~~     -->
86   <sect1 id="introduction"><title>Introduction</title>
87 <!--
88
89  I don't like seeing blank space :) So added *something* here.
90
91  --> 
92     <para>
93      <application>Privoxy</application>, as an heir to
94      <application>Junkbuster</application>, is an Open Source project 
95      and licensed under the GPL. As such, <application>Privoxy</application>
96      development is potentially open to anyone who has the time, knowledge,
97      and desire to contribute in any capacity. Our goals are simply to
98      continue the mission, to improve <application>Privoxy</application>, and
99      to make it available to as wide an audience as possible. 
100     </para>
101     <para>
102      One does not have to be a programmer to contribute. Packaging, testing,
103      and porting, are all important jobs as well.
104     </para>
105   </sect1>
106
107   <!--   ~~~~~       New section      ~~~~~     -->
108   <sect1 id="quickstart"><title>Quickstart to Privoxy Development</title>
109     <para>
110 You'll need an account on <ulink
111 url="http://sourceforge.net">Sourceforge</ulink> to support our development.
112 Mail your ID to the list and wait until a project manager has added you.
113 </para>
114
115 <para>
116 For the time being (read, this section is under construction), please note the
117 following guidelines for changing stuff in the code. If it is
118         <orderedlist numeration="arabic">
119                 <listitem><para>
120                 A bugfix / clean-up / cosmetic thing: shoot
121                 </para></listitem>
122                 <listitem><para>
123                 A new feature that can be turned off: shoot
124                 </para></listitem>
125                 <listitem><para>
126                 A clear improvement w/o side effects on other parts of the code: shoot
127                 </para></listitem>
128                 <listitem><para>
129                 A matter of taste: ask the list
130                 </para></listitem>
131                 <listitem><para>
132                 A major redesign of some part of the code: ask the list
133                 </para></listitem>
134         </orderedlist>  
135  </para>                
136 </sect1>        
137         
138   <!--   ~~~~~       New section      ~~~~~     -->
139   <sect1 id="documentation"><title>Documentation Guidelines</title>
140     <para>
141         All formal documents are maintained in docbook SGML and located
142         in the <computeroutput>doc/source</computeroutput> directory. You will
143         need <ulink url="http://www.docbook.org">docbook</ulink> and the
144         docbook stylesheets (or comparable alternatives), and either 
145         <application>jade</application> or <application>openjade</application> 
146         installed in order to build docs from source. Currently there is 
147         <ulink
148         url="../user-manual/index.html"><citetitle>user-manual</citetitle></ulink>,
149         <ulink
150         url="../faq/index.html"><citetitle>FAQ</citetitle></ulink>,
151         and, of course this, the <citetitle>developer-manual</citetitle> in
152         this format.
153         </para>
154         <para>
155          Other, less formal documents (e.g. README, LICENSE) are 
156          maintained as plain text files in the toplevel source 
157          directory.
158         </para>
159         <para>
160          Packagers are encouraged to include this documentation. For those
161          without the ability to build the docs locally, text versions of 
162          each are kept in CVS. Or HTML versions can be downloaded from the <ulink
163          url="http://www.privoxy.org">www.privoxy.org</ulink> website, which
164          should be fairly current.
165         </para>
166         <para>
167           Formal documents are built with the Makefile targets of 
168           <computeroutput>make dok</computeroutput>, or alternately
169           <computeroutput>make redhat-dok</computeroutput>. If you 
170           have problems, try both. The build process uses the document 
171           SGML sources in <computeroutput>doc/source</computeroutput> to
172           update all text files in <computeroutput>doc/text</computeroutput>
173           and to update all HTML documents in
174           <computeroutput>doc/webserver</computeroutput>.
175         </para>
176         <para>
177          Documentation writers should please make sure documents build 
178          successfully before committing to CVS.
179         </para>
180         <para>
181         How do you update the webserver (i.e. the pages on privoxy.org)?
182         <orderedlist numeration="arabic">
183                 <listitem><para>
184         First, build the docs by running <computeroutput>make
185         dok</computeroutput> (or alternately <computeroutput>make
186         redhat-dok</computeroutput>).                 
187                 </para></listitem>
188                 <listitem><para>
189         Run <computeroutput>make webserver</computeroutput> which copies all files from
190 <computeroutput>doc/webserver</computeroutput> to the sourceforge webserver
191 via scp.
192                 </para></listitem>
193         </orderedlist>
194   </para>
195  </sect1>
196
197 <!--     <listitem><para>be consistent with the redirect script (i.e. the <application>Privoxy</application> program -->
198 <!--       points via the redirect URL at sf to valid end-points in the document)</para></listitem> -->
199
200   <!--   ~~~~~       New section      ~~~~~     -->
201   <sect1 id="coding"><title>Coding Guidelines</title>
202
203     <sect2 id="s1"><title>Introduction</title>
204
205     <para>This set of standards is designed to make our lives easier.  It is
206     developed with the simple goal of helping us keep the "new and improved
207     <application>Privoxy</application>" consistent and reliable. Thus making
208     maintenance easier and increasing chances of success of the
209     project.</para>
210
211     <para>And that of course comes back to us as individuals. If we can
212     increase our development and product efficiencies then we can solve more
213     of the request for changes/improvements and in general feel good about
214     ourselves. ;-></para>
215
216   </sect2>
217
218     <sect2 id="s2"><title>Using Comments</title>
219  
220
221     <sect3 id="s3"><title>Comment, Comment, Comment</title>
222
223     <para><emphasis>Explanation:</emphasis></para>
224
225     <para>Comment as much as possible without commenting the obvious.
226     For example do not comment "aVariable is equal to bVariable".
227     Instead explain why aVariable should be equal to the bVariable.
228     Just because a person can read code does not mean they will
229     understand why or what is being done. A reader may spend a lot
230     more time figuring out what is going on when a simple comment
231     or explanation would have prevented the extra research. Please
232     help your brother IJB'ers out!</para>
233
234     <para>The comments will also help justify the intent of the code.
235     If the comment describes something different than what the code
236     is doing then maybe a programming error is occurring.</para>
237
238     <para><emphasis>Example:</emphasis></para>
239 <programlisting>
240 /* if page size greater than 1k ... */
241 if ( PageLength() > 1024 )
242 {
243     ... "block" the page up ...
244 }
245
246 /* if page size is small, send it in blocks */
247 if ( PageLength() > 1024 )
248 {
249     ... "block" the page up ...
250 }
251
252 This demonstrates 2 cases of "what not to do".  The first is a
253 "syntax comment".  The second is a comment that does not fit what
254 is actually being done.
255 </programlisting>
256   </sect3>
257
258     
259
260     <sect3 id="s4"><title>Use blocks for comments</title>
261
262     <para><emphasis>Explanation:</emphasis></para>
263
264     <para>Comments can help or they can clutter. They help when they
265     are differentiated from the code they describe. One line
266     comments do not offer effective separation between the comment
267     and the code. Block identifiers do, by surrounding the code
268     with a clear, definable pattern.</para>
269
270     <para><emphasis>Example:</emphasis></para>
271 <programlisting>
272 /*********************************************************************
273  * This will stand out clearly in your code!
274  *********************************************************************/
275 if ( thisVariable == thatVariable )
276 {
277    DoSomethingVeryImportant();
278 }
279
280
281 /* unfortunately, this may not */
282 if ( thisVariable == thatVariable )
283 {
284    DoSomethingVeryImportant();
285 }
286
287
288 if ( thisVariable == thatVariable ) /* this may not either */
289 {
290    DoSomethingVeryImportant();
291 }</programlisting>
292
293     <para><emphasis>Exception:</emphasis></para>
294
295     <para>If you are trying to add a small logic comment and do not
296     wish to "disrubt" the flow of the code, feel free to use a 1
297     line comment which is NOT on the same line as the code.</para>
298
299     
300   </sect3>
301     
302
303     <sect3 id="s5"><title>Keep Comments on their own line</title>
304
305     <para><emphasis>Explanation:</emphasis></para>
306
307     <para>It goes back to the question of readability. If the comment
308     is on the same line as the code it will be harder to read than
309     the comment that is on its own line.</para>
310
311     <para>There are three exceptions to this rule, which should be
312     violated freely and often: during the definition of variables,
313     at the end of closing braces, when used to comment
314     parameters.</para>
315
316     <para><emphasis>Example:</emphasis></para>
317 <programlisting>
318 /*********************************************************************
319  * This will stand out clearly in your code,
320  * But the second example won't.
321  *********************************************************************/
322 if ( thisVariable == thatVariable )
323 {
324    DoSomethingVeryImportant();
325 }
326
327 if ( thisVariable == thatVariable ) /*can you see me?*/
328 {
329    DoSomethingVeryImportant(); /*not easily*/
330 }
331
332
333 /*********************************************************************
334  * But, the encouraged exceptions:
335  *********************************************************************/
336 int urls_read     = 0;     /* # of urls read + rejected */
337 int urls_rejected = 0;     /* # of urls rejected */
338
339 if ( 1 == X )
340 {
341    DoSomethingVeryImportant();
342 }
343
344
345 short DoSomethingVeryImportant(
346    short firstparam,   /* represents something */
347    short nextparam     /* represents something else */ )
348 {
349    ...code here...
350
351 }   /* -END- DoSomethingVeryImportant */
352 </programlisting>
353   </sect3>
354     
355
356     <sect3 id="s6"><title>Comment each logical step</title>
357
358     <para><emphasis>Explanation:</emphasis></para>
359
360     <para>Logical steps should be commented to help others follow the
361     intent of the written code and comments will make the code more
362     readable.</para>
363
364     <para>If you have 25 lines of code without a comment, you should
365     probably go back into it to see where you forgot to put
366     one.</para>
367
368     <para>Most "for", "while", "do", etc... loops _probably_ need a
369     comment. After all, these are usually major logic
370     containers.</para>
371
372     
373   </sect3>
374     
375
376     <sect3 id="s7"><title>Comment All Functions Thoroughly</title>
377
378     <para><emphasis>Explanation:</emphasis></para>
379
380     <para>A reader of the code should be able to look at the comments
381     just prior to the beginning of a function and discern the
382     reason for its existence and the consequences of using it. The
383     reader should not have to read through the code to determine if
384     a given function is safe for a desired use. The proper
385     information thoroughly presented at the introduction of a
386     function not only saves time for subsequent maintenance or
387     debugging, it more importantly aids in code reuse by allowing a
388     user to determine the safety and applicability of any function
389     for the problem at hand. As a result of such benefits, all
390     functions should contain the information presented in the
391     addendum section of this document.</para>
392
393     
394   </sect3>
395     
396
397     <sect3 id="s8"><title>Comment at the end of braces if the
398     content is more than one screen length</title>
399
400     <para><emphasis>Explanation:</emphasis></para>
401
402     <para>Each closing brace should be followed on the same line by a
403     comment that describes the origination of the brace if the
404     original brace is off of the screen, or otherwise far away from
405     the closing brace. This will simplify the debugging,
406     maintenance, and readability of the code.</para>
407
408     <para>As a suggestion , use the following flags to make the
409     comment and its brace more readable:</para>
410
411     <para>use following a closing brace: } /* -END- if() or while ()
412     or etc... */</para>
413
414     <para><emphasis>Example:</emphasis></para>
415 <programlisting>
416 if ( 1 == X )
417 {
418    DoSomethingVeryImportant();
419    ...some long list of commands...
420 } /* -END- if x is 1 */
421
422 or:
423
424 if ( 1 == X )
425 {
426    DoSomethingVeryImportant();
427    ...some long list of commands...
428 } /* -END- if ( 1 == X ) */
429 </programlisting>
430   </sect3>
431     
432   </sect2>
433
434     <sect2 id="s9"><title>Naming Conventions</title>
435
436     
437
438     <sect3 id="s10"><title>Variable Names</title>
439
440     <para><emphasis>Explanation:</emphasis></para>
441
442     <para>Use all lowercase, and seperate words via an underscore
443     ('_'). Do not start an identifier with an underscore. (ANSI C
444     reserves these for use by the compiler and system headers.) Do
445     not use identifiers which are reserved in ANSI C++. (E.g.
446     template, class, true, false, ...). This is in case we ever
447     decide to port Privoxy to C++.</para>
448
449     <para><emphasis>Example:</emphasis></para>
450 <programlisting>
451 int ms_iis5_hack = 0;</programlisting>
452
453     <para><emphasis>Instead of:</emphasis></para>
454
455     <para>
456 <programlisting>
457 int msiis5hack = 0; int msIis5Hack = 0;
458 </programlisting>
459 </para>
460
461     
462
463   </sect3>    
464
465     <sect3 id="s11"><title>Function Names</title>
466
467     <para><emphasis>Explanation:</emphasis></para>
468
469     <para>Use all lowercase, and seperate words via an underscore
470     ('_'). Do not start an identifier with an underscore. (ANSI C
471     reserves these for use by the compiler and system headers.) Do
472     not use identifiers which are reserved in ANSI C++. (E.g.
473     template, class, true, false, ...). This is in case we ever
474     decide to port Privoxy to C++.</para>
475
476     <para><emphasis>Example:</emphasis></para>
477 <programlisting>
478 int load_some_file( struct client_state *csp )</programlisting>
479
480     <para><emphasis>Instead of:</emphasis></para>
481
482     <para>
483 <programlisting>
484 int loadsomefile( struct client_state *csp )
485 int loadSomeFile( struct client_state *csp )
486 </programlisting>
487 </para>
488
489     
490   </sect3>
491     
492
493     <sect3 id="s12"><title>Header file prototypes</title>
494
495     <para><emphasis>Explanation:</emphasis></para>
496
497     <para>Use a descriptive parameter name in the function prototype
498     in header files. Use the same parameter name in the header file
499     that you use in the c file.</para>
500
501     <para><emphasis>Example:</emphasis></para>
502 <programlisting>
503 (.h) extern int load_aclfile( struct client_state *csp );
504 (.c) int load_aclfile( struct client_state *csp )</programlisting>
505
506     <para><emphasis>Instead of:</emphasis>
507 <programlisting>
508 (.h) extern int load_aclfile( struct client_state * ); or 
509 (.h) extern int load_aclfile(); 
510 (.c) int load_aclfile( struct client_state *csp )
511 </programlisting>
512 </para>
513
514     
515   </sect3>
516     
517
518     <sect3 id="s13"><title>Enumerations, and #defines</title>
519
520     <para><emphasis>Explanation:</emphasis></para>
521
522     <para>Use all capital letters, with underscores between words. Do
523     not start an identifier with an underscore. (ANSI C reserves
524     these for use by the compiler and system headers.)</para>
525
526     <para><emphasis>Example:</emphasis></para>
527 <programlisting>
528 (enumeration) : enum Boolean { FALSE, TRUE };
529 (#define) : #define DEFAULT_SIZE 100;</programlisting>
530
531     <para><emphasis>Note:</emphasis> We have a standard naming scheme for #defines
532     that toggle a feature in the preprocessor: FEATURE_>, where
533     > is a short (preferably 1 or 2 word) description.</para>
534
535     <para><emphasis>Example:</emphasis></para>
536 <programlisting>
537 #define FEATURE_FORCE 1
538
539 #ifdef FEATURE_FORCE
540 #define FORCE_PREFIX blah
541 #endif /* def FEATURE_FORCE */
542 </programlisting>
543   </sect3>
544     
545
546     <sect3 id="s14"><title>Constants</title>
547
548     <para><emphasis>Explanation:</emphasis></para>
549
550     <para>Spell common words out entirely (do not remove vowels).</para>
551
552     <para>Use only widely-known domain acronyms and abbreviations.
553     Capitalize all letters of an acronym.</para>
554
555     <para>Use underscore (_) to separate adjacent acronyms and
556     abbreviations. Never terminate a name with an underscore.</para>
557
558     <para><emphasis>Example:</emphasis></para>
559 <programlisting>
560 #define USE_IMAGE_LIST 1</programlisting>
561
562     <para><emphasis>Instead of:</emphasis></para>
563
564     <para>
565 <programlisting>
566 #define USE_IMG_LST 1 or 
567 #define _USE_IMAGE_LIST 1 or
568 #define USE_IMAGE_LIST_ 1 or 
569 #define use_image_list 1 or
570 #define UseImageList 1
571 </programlisting>
572 </para>
573
574     
575   </sect3>
576
577   </sect2>
578     
579
580     <sect2 id="s15"><title>Using Space</title>
581
582     
583
584     <sect3 id="s16"><title>Put braces on a line by themselves.</title>
585
586     <para><emphasis>Explanation:</emphasis></para>
587
588     <para>The brace needs to be on a line all by itself, not at the
589     end of the statement. Curly braces should line up with the
590     construct that they're associated with. This practice makes it
591     easier to identify the opening and closing braces for a
592     block.</para>
593
594     <para><emphasis>Example:</emphasis></para>
595 <programlisting>
596 if ( this == that )
597 {
598    ...
599 }</programlisting>
600
601     <para><emphasis>Instead of:</emphasis></para>
602
603     <para>if ( this == that ) { ... }</para>
604
605     <para>or</para>
606
607     <para>if ( this == that ) { ... }</para>
608
609     <para><emphasis>Note:</emphasis> In the special case that the if-statement is
610     inside a loop, and it is trivial, i.e. it tests for a
611     condidtion that is obvious from the purpose of the block,
612     one-liners as above may optically preserve the loop structure
613     and make it easier to read.</para>
614
615     <para><emphasis>Status:</emphasis> developer-discrection.</para>
616
617     <para><emphasis>Example exception:</emphasis></para>
618 <programlisting>
619 while ( more lines are read )
620 {
621    /* Please document what is/is not a comment line here */
622    if ( it's a comment ) continue;
623
624    do_something( line );
625 }
626 </programlisting>
627   </sect3>
628     
629
630     <sect3 id="s17"><title>ALL control statements should have a
631     block</title>
632
633     <para><emphasis>Explanation:</emphasis></para>
634
635     <para>Using braces to make a block will make your code more
636     readable and less prone to error. All control statements should
637     have a block defined.</para>
638
639     <para><emphasis>Example:</emphasis></para>
640 <programlisting>
641 if ( this == that )
642 {
643    DoSomething();
644    DoSomethingElse();
645 }</programlisting>
646
647     <para><emphasis>Instead of:</emphasis></para>
648
649     <para>if ( this == that ) DoSomething(); DoSomethingElse();</para>
650
651     <para>or</para>
652
653     <para>if ( this == that ) DoSomething();</para>
654
655     <para><emphasis>Note:</emphasis> The first example in "Instead of" will execute
656     in a manner other than that which the developer desired (per
657     indentation). Using code braces would have prevented this
658     "feature". The "explanation" and "exception" from the point
659     above also applies.</para>
660
661     
662   </sect3>
663     
664
665     <sect3 id="s18"><title>Do not belabor/blow-up boolean
666     expressions</title>
667
668     <para><emphasis>Example:</emphasis></para>
669 <programlisting>
670 structure->flag = ( condition );</programlisting>
671
672     <para><emphasis>Instead of:</emphasis></para>
673
674     <para>if ( condition ) { structure->flag = 1; } else {
675     structure->flag = 0; }</para>
676
677     <para><emphasis>Note:</emphasis> The former is readable and consice. The later
678     is wordy and inefficient. Please assume that any developer new
679     to the project has at least a "good" knowledge of C/C++. (Hope
680     I do not offend by that last comment ... 8-)</para>
681
682     
683   </sect3>
684     
685
686     <sect3 id="s19"><title>Use white space freely because it is
687     free</title>
688
689     <para><emphasis>Explanation:</emphasis></para>
690
691     <para>Make it readable. The notable exception to using white space
692     freely is listed in the next guideline.</para>
693
694     <para><emphasis>Example:</emphasis></para>
695 <programlisting>
696 int firstValue   = 0;
697 int someValue    = 0;
698 int anotherValue = 0;
699 int thisVariable = 0;
700
701 if ( thisVariable == thatVariable )
702
703 firstValue = oldValue + ( ( someValue - anotherValue ) - whatever )
704 </programlisting>
705   </sect3>
706     
707
708     <sect3 id="s20"><title>Don't use white space around structure
709     operators</title>
710
711     <para><emphasis>Explanation:</emphasis></para>
712
713     <para>- structure pointer operator ( "->" ) - member operator (
714     "." ) - functions and parentheses</para>
715
716     <para>It is a general coding practice to put pointers, references,
717     and function parentheses next to names. With spaces, the
718     connection between the object and variable/function name is not
719     as clear.</para>
720
721     <para><emphasis>Example:</emphasis></para>
722 <programlisting>
723 aStruct->aMember;
724 aStruct.aMember;
725 FunctionName();</programlisting>
726
727     <para><emphasis>Instead of:</emphasis> aStruct -> aMember; aStruct . aMember;
728     FunctionName ();</para>
729
730     
731   </sect3>
732     
733
734     <sect3 id="s21"><title>Make the last brace of a function stand
735     out</title>
736
737     <para><emphasis>Example:</emphasis></para>
738 <programlisting>
739 int function1( ... )
740 {
741    ...code...
742    return( retCode );
743
744 }   /* -END- function1 */
745
746
747 int function2( ... )
748 {
749 }   /* -END- function2 */
750 </programlisting>
751
752     <para><emphasis>Instead of:</emphasis></para>
753
754     <para>int function1( ... ) { ...code... return( retCode ); } int
755     function2( ... ) { }</para>
756
757     <para><emphasis>Note:</emphasis> Use 1 blank line before the closing brace and 2
758     lines afterwards. This makes the end of function standout to
759     the most casual viewer. Although function comments help
760     seperate functions, this is still a good coding practice. In
761     fact, I follow these rules when using blocks in "for", "while",
762     "do" loops, and long if {} statements too. After all whitespace
763     is free!</para>
764
765     <para><emphasis>Status:</emphasis> developer-discrection on the number of blank
766     lines. Enforced is the end of function comments.</para>
767
768     
769   </sect3>
770     
771
772     <sect3 id="s22"><title>Use 3 character indentions</title>
773
774     <para><emphasis>Explanation:</emphasis></para>
775
776     <para>If some use 8 character TABs and some use 3 character TABs,
777     the code can look *very* ragged. So use 3 character indentions
778     only. If you like to use TABs, pass your code through a filter
779     such as "expand -t3" before checking in your code.</para>
780
781     <para><emphasis>Example:</emphasis></para>
782 <programlisting>
783 static const char * const url_code_map[256] =
784 {
785    NULL, ...
786 };
787
788
789 int function1( ... )
790 {
791    if ( 1 )
792    {
793       return( ALWAYS_TRUE );
794    }
795    else
796    {
797       return( HOW_DID_YOU_GET_HERE );
798    }
799
800    return( NEVER_GETS_HERE );
801
802 }
803 </programlisting>
804   </sect3>
805
806   </sect2>
807     
808
809     <sect2 id="s23"><title>Initializing</title>
810
811     
812
813     <sect3 id="s24"><title>Initialize all variables</title>
814
815     <para><emphasis>Explanation:</emphasis></para>
816
817     <para>Do not assume that the variables declared will not be used
818     until after they have been assigned a value somewhere else in
819     the code. Remove the chance of accidentally using an unassigned
820     variable.</para>
821
822     <para><emphasis>Example:</emphasis></para>
823 <programlisting>
824 short anShort = 0;
825 float aFloat  = 0;
826 struct *ptr = NULL;</programlisting>
827
828     <para><emphasis>Note:</emphasis> It is much easier to debug a SIGSEGV if the
829     message says you are trying to access memory address 00000000
830     and not 129FA012; or arrayPtr[20] causes a SIGSEV vs.
831     arrayPtr[0].</para>
832
833     <para><emphasis>Status:</emphasis> developer-discrection if and only if the
834     variable is assigned a value "shortly after" declaration.</para>
835
836   </sect3>
837   </sect2>
838     
839
840     <sect2 id="s25"><title>Functions</title>
841
842     
843
844     <sect3 id="s26"><title>Name functions that return a boolean as a
845     question.</title>
846
847     <para><emphasis>Explanation:</emphasis></para>
848
849     <para>Value should be phrased as a question that would logically
850     be answered as a true or false statement</para>
851
852     <para><emphasis>Example:</emphasis></para>
853 <programlisting>
854 ShouldWeBlockThis();
855 ContainsAnImage();
856 IsWebPageBlank();
857 </programlisting>
858   </sect3>
859     
860
861     <sect3 id="s27"><title>Always specify a return type for a
862     function.</title>
863
864     <para><emphasis>Explanation:</emphasis></para>
865
866     <para>The default return for a function is an int. To avoid
867     ambiguity, create a return for a function when the return has a
868     purpose, and create a void return type if the function does not
869     need to return anything.</para>
870
871     
872   </sect3>
873     
874
875     <sect3 id="s28"><title>Minimize function calls when iterating by
876     using variables</title>
877
878     <para><emphasis>Explanation:</emphasis></para>
879
880     <para>It is easy to write the following code, and a clear argument
881     can be made that the code is easy to understand:</para>
882
883     <para><emphasis>Example:</emphasis></para>
884 <programlisting>
885 for ( size_t cnt = 0; cnt &lt; blockListLength(); cnt ++ )
886 {
887    ....
888 }</programlisting>
889
890     <para><emphasis>Note:</emphasis> Unfortunately, this makes a function call for
891     each and every iteration. This increases the overhead in the
892     program, because the compiler has to look up the function each
893     time, call it, and return a value. Depending on what occurs in
894     the blockListLength() call, it might even be creating and
895     destroying structures with each iteration, even though in each
896     case it is comparing "cnt" to the same value, over and over.
897     Remember too - even a call to blockListLength() is a function
898     call, with the same overhead.</para>
899
900     <para>Instead of using a function call during the iterations,
901     assign the value to a variable, and evaluate using the
902     variable.</para>
903
904     <para><emphasis>Example:</emphasis></para>
905 <programlisting>
906 size_t len = blockListLength();
907
908 for ( size_t cnt = 0; cnt &lt; len; cnt ++ )
909 {
910    ....
911 }</programlisting>
912
913     <para><emphasis>Exceptions:</emphasis> if the value of blockListLength() *may*
914     change or could *potentially* change, then you must code the
915     function call in the for/while loop.</para>
916
917     
918   </sect3>
919     
920
921     <sect3 id="s29"><title>Pass and Return by Const Reference</title>
922
923     <para><emphasis>Explanation:</emphasis></para>
924
925     <para>This allows a developer to define a const pointer and call
926     your function. If your function does not have the const
927     keyword, we may not be able to use your function. Consider
928     strcmp, if it were defined as: extern int strcmp( char *s1,
929     char *s2 );</para>
930
931     <para>I could then not use it to compare argv's in main: int main(
932     int argc, const char *argv[] ) { strcmp( argv[0], "privoxy"
933     ); }</para>
934
935     <para>Both these pointers are *const*! If the c runtime library
936     maintainers do it, we should too.</para>
937
938     
939   </sect3>
940     
941
942     <sect3 id="s30"><title>Pass and Return by Value</title>
943
944     <para><emphasis>Explanation:</emphasis></para>
945
946     <para>Most structures cannot fit onto a normal stack entry (i.e.
947     they are not 4 bytes or less). Aka, a function declaration
948     like: int load_aclfile( struct client_state csp )</para>
949
950     <para>would not work. So, to be consistent, we should declare all
951     prototypes with "pass by value": int load_aclfile( struct
952     client_state *csp )</para>
953
954     
955   </sect3>
956     
957
958     <sect3 id="s31"><title>Names of include files</title>
959
960     <para><emphasis>Explanation:</emphasis></para>
961
962     <para>Your include statements should contain the file name without
963     a path. The path should be listed in the Makefile, using -I as
964     processor directive to search the indicated paths. An exception
965     to this would be for some proprietary software that utilizes a
966     partial path to distinguish their header files from system or
967     other header files.</para>
968
969     <para><emphasis>Example:</emphasis></para>
970 <programlisting>
971 #include &lt;iostream.h&gt;     /* This is not a local include */
972 #include "config.h"       /* This IS a local include */
973 </programlisting>
974
975     <para><emphasis>Exception:</emphasis></para>
976
977     <para>
978 <programlisting>
979 /* This is not a local include, but requires a path element. */ 
980 #include &lt;sys/fileName.h&gt;
981 </programlisting>
982 </para>
983
984     <para><emphasis>Note:</emphasis> Please! do not add "-I." to the Makefile
985     without a _very_ good reason. This duplicates the #include
986     "file.h" behaviour.</para>
987
988     
989   </sect3>
990     
991
992     <sect3 id="s32"><title>Provide multiple inclusion
993     protection</title>
994
995     <para><emphasis>Explanation:</emphasis></para>
996
997     <para>Prevents compiler and linker errors resulting from
998     redefinition of items.</para>
999
1000     <para>Wrap each header file with the following syntax to prevent
1001     multiple inclusions of the file. Of course, replace PROJECT_H
1002     with your file name, with "." Changed to "_", and make it
1003     uppercase.</para>
1004
1005     <para><emphasis>Example:</emphasis></para>
1006 <programlisting>
1007 #ifndef PROJECT_H_INCLUDED
1008 #define PROJECT_H_INCLUDED
1009  ...
1010 #endif /* ndef PROJECT_H_INCLUDED */
1011 </programlisting>
1012   </sect3>
1013     
1014
1015     <sect3 id="s33"><title>Use `extern "C"` when appropriate</title>
1016
1017     <para><emphasis>Explanation:</emphasis></para>
1018
1019     <para>If our headers are included from C++, they must declare our
1020     functions as `extern "C"`. This has no cost in C, but increases
1021     the potential re-usability of our code.</para>
1022
1023     <para><emphasis>Example:</emphasis></para>
1024 <programlisting>
1025 #ifdef __cplusplus
1026 extern "C"
1027 {
1028 #endif /* def __cplusplus */
1029
1030 ... function definitions here ...
1031
1032 #ifdef __cplusplus
1033 }
1034 #endif /* def __cplusplus */
1035 </programlisting>
1036   </sect3>
1037     
1038
1039     <sect3 id="s34"><title>Where Possible, Use Forward Struct
1040     Declaration Instead of Includes</title>
1041
1042     <para><emphasis>Explanation:</emphasis></para>
1043
1044     <para>Useful in headers that include pointers to other struct's.
1045     Modifications to excess header files may cause needless
1046     compiles.</para>
1047
1048     <para><emphasis>Example:</emphasis></para>
1049 <programlisting>
1050 /*********************************************************************
1051  * We're avoiding an include statement here!
1052  *********************************************************************/
1053 struct file_list;
1054 extern file_list *xyz;</programlisting>
1055
1056     <para><emphasis>Note:</emphasis> If you declare "file_list xyz;" (without the
1057     pointer), then including the proper header file is necessary.
1058     If you only want to prototype a pointer, however, the header
1059     file is unneccessary.</para>
1060
1061     <para><emphasis>Status:</emphasis> Use with discrection.</para>
1062
1063     
1064   </sect3>
1065   </sect2>
1066
1067     <sect2 id="s35"><title>General Coding Practices</title>
1068
1069     
1070
1071     <sect3 id="s36"><title>Turn on warnings</title>
1072
1073     <para><emphasis>Explanation</emphasis></para>
1074
1075     <para>Compiler warnings are meant to help you find bugs. You
1076     should turn on as many as possible. With GCC, the switch is
1077     "-Wall". Try and fix as many warnings as possible.</para>
1078
1079     
1080   </sect3>
1081     
1082
1083     <sect3 id="s37"><title>Provide a default case for all switch
1084     statements</title>
1085
1086     <para><emphasis>Explanation:</emphasis></para>
1087
1088     <para>What you think is guaranteed is never really guaranteed. The
1089     value that you don't think you need to check is the one that
1090     someday will be passed. So, to protect yourself from the
1091     unknown, always have a default step in a switch statement.</para>
1092
1093     <para><emphasis>Example:</emphasis></para>
1094 <programlisting>
1095 switch( hash_string( cmd ) )
1096 {
1097    case hash_actions_file :
1098       ... code ...
1099       break;
1100
1101    case hash_confdir :
1102       ... code ...
1103       break;
1104
1105    default :
1106       log_error( ... );
1107       ... anomly code goes here ...
1108       continue; / break; / exit( 1 ); / etc ...
1109
1110 } /* end switch( hash_string( cmd ) ) */</programlisting>
1111
1112     <para><emphasis>Note:</emphasis> If you already have a default condition, you
1113     are obviously exempt from this point. Of note, most of the
1114     WIN32 code calls `DefWindowProc' after the switch statement.
1115     This API call *should* be included in a default statement.</para>
1116
1117     <para><emphasis>Another Note:</emphasis> This is not so much a readability issue
1118     as a robust programming issue. The "anomly code goes here" may
1119     be no more than a print to the STDERR stream (as in
1120     load_config). Or it may really be an ABEND condition.</para>
1121
1122     <para><emphasis>Status:</emphasis> Programmer discretion is advised.</para>
1123
1124     
1125   </sect3>
1126     
1127
1128     <sect3 id="s38"><title>Try to avoid falling through cases in a
1129     switch statement.</title>
1130
1131     <para><emphasis>Explanation:</emphasis></para>
1132
1133     <para>In general, you will want to have a 'break' statement within
1134     each 'case' of a switch statement. This allows for the code to
1135     be more readable and understandable, and furthermore can
1136     prevent unwanted surprises if someone else later gets creative
1137     and moves the code around.</para>
1138
1139     <para>The language allows you to plan the fall through from one
1140     case statement to another simply by omitting the break
1141     statement within the case statement. This feature does have
1142     benefits, but should only be used in rare cases. In general,
1143     use a break statement for each case statement.</para>
1144
1145     <para>If you choose to allow fall through, you should comment both
1146     the fact of the fall through and reason why you felt it was
1147     necessary.</para>
1148
1149     
1150   </sect3>
1151     
1152
1153     <sect3 id="s39"><title>Use 'long' or 'short' Instead of
1154     'int'</title>
1155
1156     <para><emphasis>Explanation:</emphasis></para>
1157
1158     <para>On 32-bit platforms, int usually has the range of long. On
1159     16-bit platforms, int has the range of short.</para>
1160
1161     <para><emphasis>Status:</emphasis> open-to-debate. In the case of most FSF
1162     projects (including X/GNU-Emacs), there are typedefs to int4,
1163     int8, int16, (or equivalence ... I forget the exact typedefs
1164     now). Should we add these to IJB now that we have a "configure"
1165     script?</para>
1166
1167     
1168   </sect3>
1169     
1170
1171     <sect3 id="s40"><title>Don't mix size_t and other types</title>
1172
1173     <para><emphasis>Explanation:</emphasis></para>
1174
1175     <para>The type of size_t varies across platforms. Do not make
1176     assumptions about whether it is signed or unsigned, or about
1177     how long it is. Do not compare a size_t against another
1178     variable of a different type (or even against a constant)
1179     without casting one of the values. Try to avoid using size_t if
1180     you can.</para>
1181
1182     
1183   </sect3>
1184     
1185
1186     <sect3 id="s41"><title>Declare each variable and struct on its
1187     own line.</title>
1188
1189     <para><emphasis>Explanation:</emphasis></para>
1190
1191     <para>It can be tempting to declare a series of variables all on
1192     one line. Don't.</para>
1193
1194     <para><emphasis>Example:</emphasis></para>
1195 <programlisting>
1196 long a = 0;
1197 long b = 0;
1198 long c = 0;</programlisting>
1199
1200     <para><emphasis>Instead of:</emphasis></para>
1201
1202     <para>long a, b, c;</para>
1203
1204     <para><emphasis>Explanation:</emphasis> - there is more room for comments on the
1205     individual variables - easier to add new variables without
1206     messing up the original ones - when searching on a variable to
1207     find its type, there is less clutter to "visually"
1208     eliminate</para>
1209
1210     <para><emphasis>Exceptions:</emphasis> when you want to declare a bunch of loop
1211     variables or other trivial variables; feel free to declare them
1212     on 1 line. You should, although, provide a good comment on
1213     their functions.</para>
1214
1215     <para><emphasis>Status:</emphasis> developer-discrection.</para>
1216
1217     
1218   </sect3>
1219     
1220
1221     <sect3 id="s42"><title>Use malloc/zalloc sparingly</title>
1222
1223     <para><emphasis>Explanation:</emphasis></para>
1224
1225     <para>Create a local stuct (on the stack) if the variable will
1226     live and die within the context of one function call.</para>
1227
1228     <para>Only "malloc" a struct (on the heap) if the variable's life
1229     will extend beyond the context of one function call.</para>
1230
1231     <para><emphasis>Example:</emphasis></para>
1232 <programlisting>
1233 If a function creates a struct and stores a pointer to it in a
1234 list, then it should definately be allocated via `malloc'.
1235 </programlisting>
1236   </sect3>
1237     
1238
1239     <sect3 id="s43"><title>The Programmer Who Uses 'malloc' is
1240     Responsible for Ensuring 'free'</title>
1241
1242     <para><emphasis>Explanation:</emphasis></para>
1243
1244     <para>If you have to "malloc" an instance, you are responsible for
1245     insuring that the instance is `free'd, even if the deallocation
1246     event falls within some other programmer's code. You are also
1247     responsible for ensuring that deletion is timely (i.e. not too
1248     soon, not too late). This is known as "low-coupling" and is a
1249     "good thing (tm)". You may need to offer a
1250     free/unload/destuctor type function to accomodate this.</para>
1251
1252     <para><emphasis>Example:</emphasis></para>
1253 <programlisting>
1254 int load_re_filterfile( struct client_state *csp ) { ... }
1255 static void unload_re_filterfile( void *f ) { ... }</programlisting>
1256
1257     <para><emphasis>Exceptions:</emphasis></para>
1258
1259     <para>The developer cannot be expected to provide `free'ing
1260     functions for C run-time library functions ... such as
1261     `strdup'.</para>
1262
1263     <para><emphasis>Status:</emphasis> developer-discrection. The "main" use of this
1264     standard is for allocating and freeing data structures (complex
1265     or nested).</para>
1266
1267     
1268   </sect3>
1269     
1270
1271     <sect3 id="s44"><title>Add loaders to the `file_list' structure
1272     and in order</title>
1273
1274     <para><emphasis>Explanation:</emphasis></para>
1275
1276     <para>I have ordered all of the "blocker" file code to be in alpha
1277     order. It is easier to add/read new blockers when you expect a
1278     certain order.</para>
1279
1280     <para><emphasis>Note:</emphasis> It may appear that the alpha order is broken in
1281     places by POPUP tests coming before PCRS tests. But since
1282     POPUPs can also be referred to as KILLPOPUPs, it is clear that
1283     it should come first.</para>
1284
1285     
1286   </sect3>
1287     
1288
1289     <sect3 id="s45"><title>"Uncertain" new code and/or changes to
1290     exitinst code, use FIXME</title>
1291
1292     <para><emphasis>Explanation:</emphasis></para>
1293
1294     <para>If you have enough confidence in new code or confidence in
1295     your changes, but are not *quite* sure of the reprocussions,
1296     add this:</para>
1297
1298     <para>/* FIXME: this code has a logic error on platform XYZ, *
1299     attempthing to fix */ #ifdef PLATFORM ...changed code here...
1300     #endif</para>
1301
1302     <para>or:</para>
1303
1304     <para>/* FIXME: I think the original author really meant this...
1305     */ ...changed code here...</para>
1306
1307     <para>or:</para>
1308
1309     <para>/* FIXME: new code that *may* break something else... */
1310     ...new code here...</para>
1311
1312     <para><emphasis>Note:</emphasis> If you make it clear that this may or may not
1313     be a "good thing (tm)", it will be easier to identify and
1314     include in the project (or conversly exclude from the
1315     project).</para>
1316
1317     
1318   </sect3>
1319
1320   </sect2>
1321
1322     <sect2 id="s46"><title>Addendum: Template for files and function
1323     comment blocks:</title>
1324
1325     <para><emphasis>Example for file comments:</emphasis></para>
1326 <programlisting>
1327 const char FILENAME_rcs[] = "$Id: developer-manual.sgml,v 1.21 2002/04/04 06:48:37 hal9 Exp $";
1328 /*********************************************************************
1329  *
1330  * File        :  $S<!-- Break CVS Substitution -->ource$
1331  *
1332  * Purpose     :  (Fill me in with a good description!)
1333  *
1334  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
1335  *                Privoxy team. http://www.privoxy.org/
1336  *
1337  *                Based on the Internet Junkbuster originally written
1338  *                by and Copyright (C) 1997 Anonymous Coders and
1339  *                Junkbusters Corporation.  http://www.junkbusters.com
1340  *
1341  *                This program is free software; you can redistribute it
1342  *                and/or modify it under the terms of the GNU General
1343  *                Public License as published by the Free Software
1344  *                Foundation; either version 2 of the License, or (at
1345  *                your option) any later version.
1346  *
1347  *                This program is distributed in the hope that it will
1348  *                be useful, but WITHOUT ANY WARRANTY; without even the
1349  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
1350  *                PARTICULAR PURPOSE.  See the GNU General Public
1351  *                License for more details.
1352  *
1353  *                The GNU General Public License should be included with
1354  *                this file.  If not, you can view it at
1355  *                http://www.gnu.org/copyleft/gpl.html
1356  *                or write to the Free Software Foundation, Inc., 59
1357  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
1358  *
1359  * Revisions   :
1360  *    $L<!-- Break CVS Substitution -->og$
1361  *
1362  *********************************************************************/
1363
1364
1365 #include "config.h"
1366
1367    ...necessary include files for us to do our work...
1368
1369 const char FILENAME_h_rcs[] = FILENAME_H_VERSION;
1370 </programlisting>
1371
1372     <para><emphasis>Note:</emphasis> This declares the rcs variables that should be
1373     added to the "show-proxy-args" page. If this is a brand new
1374     creation by you, you are free to change the "Copyright" section
1375     to represent the rights you wish to maintain.</para>
1376
1377     <para><emphasis>Note:</emphasis> The formfeed character that is present right
1378     after the comment flower box is handy for (X|GNU)Emacs users to
1379     skip the verbige and get to the heart of the code (via
1380     `forward-page' and `backward-page'). Please include it if you
1381     can.</para>
1382
1383     <para><emphasis>Example for file header comments:</emphasis></para>
1384 <programlisting>
1385 #ifndef _FILENAME_H
1386 #define _FILENAME_H
1387 #define FILENAME_H_VERSION "$Id: developer-manual.sgml,v 1.21 2002/04/04 06:48:37 hal9 Exp $"
1388 /*********************************************************************
1389  *
1390  * File        :  $S<!-- Break CVS Substitution -->ource$
1391  *
1392  * Purpose     :  (Fill me in with a good description!)
1393  *
1394  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
1395  *                Privoxy team. http://www.privoxy.org/
1396  *
1397  *                Based on the Internet Junkbuster originally written
1398  *                by and Copyright (C) 1997 Anonymous Coders and
1399  *                Junkbusters Corporation.  http://www.junkbusters.com
1400  *
1401  *                This program is free software; you can redistribute it
1402  *                and/or modify it under the terms of the GNU General
1403  *                Public License as published by the Free Software
1404  *                Foundation; either version 2 of the License, or (at
1405  *                your option) any later version.
1406  *
1407  *                This program is distributed in the hope that it will
1408  *                be useful, but WITHOUT ANY WARRANTY; without even the
1409  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
1410  *                PARTICULAR PURPOSE.  See the GNU General Public
1411  *                License for more details.
1412  *
1413  *                The GNU General Public License should be included with
1414  *                this file.  If not, you can view it at
1415  *                http://www.gnu.org/copyleft/gpl.html
1416  *                or write to the Free Software Foundation, Inc., 59
1417  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
1418  *
1419  * Revisions   :
1420  *    $L<!-- Break CVS Substitution -->og$
1421  *
1422  *********************************************************************/
1423
1424
1425 #include "project.h"
1426
1427 #ifdef __cplusplus
1428 extern "C" {
1429 #endif
1430
1431    ... function headers here ...
1432
1433
1434 /* Revision control strings from this header and associated .c file */
1435 extern const char FILENAME_rcs[];
1436 extern const char FILENAME_h_rcs[];
1437
1438
1439 #ifdef __cplusplus
1440 } /* extern "C" */
1441 #endif
1442
1443 #endif /* ndef _FILENAME_H */
1444
1445 /*
1446   Local Variables:
1447   tab-width: 3
1448   end:
1449 */
1450 </programlisting>
1451
1452     <para><emphasis>Example for function comments:</emphasis></para>
1453 <programlisting>
1454 /*********************************************************************
1455  *
1456  * Function    :  FUNCTION_NAME
1457  *
1458  * Description :  (Fill me in with a good description!)
1459  *
1460  * parameters  :
1461  *          1  :  param1 = pointer to an important thing
1462  *          2  :  x      = pointer to something else
1463  *
1464  * Returns     :  0 => Ok, everything else is an error.
1465  *
1466  *********************************************************************/
1467 int FUNCTION_NAME( void *param1, const char *x )
1468 {
1469    ...
1470    return( 0 );
1471
1472 }
1473 </programlisting>
1474
1475     <para><emphasis>Note:</emphasis> If we all follow this practice, we should be
1476     able to parse our code to create a "self-documenting" web
1477     page.</para>
1478
1479   </sect2>
1480
1481   </sect1>
1482
1483   <!--   ~~~~~       New section      ~~~~~     -->
1484   <sect1 id="cvs"><title>Version Control Guidelines</title>
1485     <para>To be filled. note on cvs comments. Don't only comment what you did,
1486     but also why you did it!
1487 </para>
1488   </sect1>
1489
1490   <!--   ~~~~~       New section      ~~~~~     -->
1491   <sect1 id="testing"><title>Testing Guidelines</title>
1492     <para>To be filled.
1493 </para>
1494
1495     <!--   ~~~~~       New section      ~~~~~     -->
1496     <sect2 id="testing-plan"><title>Testplan for releases</title>
1497       <para>
1498        Explain release numbers. major, minor. developer releases. etc.
1499
1500 <orderedlist numeration="arabic">
1501           <listitem><para>
1502 Remove any existing rpm with rpm -e
1503 </para></listitem>
1504           <listitem><para>
1505 Remove any file that was left over. This includes (but is not limited to)
1506       <itemizedlist>
1507                 <listitem><para>/var/log/privoxy</para></listitem>
1508                 <listitem><para>/etc/privoxy</para></listitem>
1509                 <listitem><para>/usr/sbin/privoxy</para></listitem>
1510                 <listitem><para>/etc/init.d/privoxy</para></listitem>
1511                 <listitem><para>/usr/doc/privoxy*</para></listitem>
1512               </itemizedlist>
1513 </para></listitem>
1514           <listitem><para>
1515 Install the rpm. Any error messages?
1516 </para></listitem>
1517           <listitem><para>start,stop,status <application>Privoxy</application> with the specific script
1518       (e.g. /etc/rc.d/init/privoxy stop). Reboot your machine. Does
1519       autostart work?</para></listitem>
1520           <listitem><para>Start browsing. Does <application>Privoxy</application> work? Logfile written?</para></listitem>
1521           <listitem><para>Remove the rpm. Any error messages? All files removed?</para></listitem>
1522         </orderedlist>
1523 </para>
1524     </sect2>
1525
1526     <!--   ~~~~~       New section      ~~~~~     -->
1527     <sect2 id="testing-report"><title>Test reports</title>
1528       <para>
1529 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>
1530 at sourceforge. Three simple steps:
1531         <itemizedlist>
1532           
1533           <listitem><para>Select category: the distribution you test on.</para></listitem>
1534           <listitem><para>Select group: the version of <application>Privoxy</application> that we are about to release.</para></listitem>
1535           <listitem><para>Fill the Summary and Detailed Description with something
1536               intelligent (keep it short and precise).</para>
1537           </listitem>
1538         </itemizedlist>
1539         Do not mail to the mailinglist (we cannot keep track on issues there).
1540       </para>
1541     </sect2>
1542     
1543   </sect1>
1544
1545   <!--   ~~~~~       New section      ~~~~~     -->
1546   <sect1 id="newrelease"><title>Releasing a new version</title>
1547     <para>
1548         To minimize trouble with distribution contents, webpage
1549         errors and the like, we strongly encourage you
1550         to follow this section if you prepare a new release of
1551         code or new pages on the webserver.
1552     </para>
1553     <para>
1554         The following programs are required to follow this process:
1555         <filename>ncftpput</filename> (ncftp), <filename>scp</filename> (ssh),
1556 <filename>gmake</filename> (GNU's version of make), autoconf, cvs, ???.
1557     </para>
1558      
1559     <sect2 id="beforerelease">
1560     <title>Before the Release</title>
1561      <para>
1562        The following <emphasis>must be done by one of the
1563        developers</emphasis> prior to each new release:
1564      </para>
1565      <para>
1566       <itemizedlist>
1567        <listitem>
1568         <para>
1569          Make sure that everybody who has worked on the code in the last
1570          couple of days has had a chance to yell <quote>no!</quote> in case
1571          they have pending changes/fixes in their pipelines.
1572         </para>
1573       </listitem> 
1574       <listitem>
1575        <para>
1576          Increment the version number in <filename>configure.in</filename> in
1577          CVS. Also, the RPM release number in
1578          <filename>configure.in</filename>. Do NOT touch version information
1579          after export from CVS. <emphasis>All packages</emphasis> will use the
1580          version and release data from <filename>configure.in</filename>.
1581          Local files should not be changed, except prior to a CVS commit!!!
1582          This way we are all on the same page!
1583        </para>
1584       </listitem> 
1585       <listitem>
1586        <para>
1587         If the default actionsfile has changed since last release,
1588         bump up its version info in this line:
1589        </para>
1590        <para> 
1591         <programlisting>
1592   {+add-header{X-Actions-File-Version: A.B} -filter -no-popups}
1593         </programlisting>
1594        </para>
1595        <para> 
1596         Then change the version info in doc/webserver/actions/index.php,
1597         line: '$required_actions_file_version = "A.B";'
1598        </para>
1599       </listitem> 
1600       <listitem>
1601        <para>
1602         Tag all files in CVS with the version number with
1603         <quote><command>cvs tag v_X_Y_Z</command></quote> (where X = major, Y
1604         = minor, Z = point). Don't use vX_Y_Z, ver_X_Y_Z, v_X.Y.Z (won't work)
1605         etc.
1606        </para>
1607       </listitem> 
1608       <listitem>
1609        <para>
1610         The first package uploaded should be the official
1611         <quote>tarball</quote> release. This is built with the
1612         <quote><command>make tarball-dist</command></quote> Makefile 
1613         target, and then can be uploaded with 
1614         <quote><command>make tarball-upload</command></quote> (see below).
1615        </para>
1616       </listitem> 
1617       </itemizedlist>
1618      </para> 
1619     </sect2>
1620     
1621     <sect2 id="newrelease-web"><title>Update the webserver</title>
1622       <para>
1623         All files must be group-readable and group-writable (or no one else
1624         will be able to change them). To update the webserver, create any
1625         pages locally in the <filename>doc/webserver</filename> directory (or
1626         create new directories under <filename>doc/webserver</filename>), then do
1627         </para>
1628         <para>
1629         <programlisting>
1630   make webserver
1631         </programlisting>
1632         </para>
1633         <para>
1634         Note that <quote><command>make dok</command></quote> 
1635      (or <quote><command>make redhat-dok</command></quote>) creates
1636         <filename>doc/webserver/user-manual</filename>,
1637         <filename>doc/webserver/developer-manual</filename>,
1638         <filename>doc/webserver/faq</filename> and
1639         <filename>doc/webserver/man-page</filename> automatically.
1640       </para>
1641       <para>
1642       Please do NOT use any other means of transferring files to the
1643       webserver. <quote><command>make webserver</command></quote> not only
1644       uploads, but will make sure that the appropriate permissions are 
1645       preserved for shared group access.
1646       </para>
1647     </sect2>
1648
1649     <sect2 id="newrelease-rpm"><title>SuSE or Red Hat</title>
1650       <para>
1651         Ensure that you have the latest code version. Hence run:
1652         </para>
1653         <para>
1654         <programlisting>
1655   cd current
1656   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
1657   cvs -z3  -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
1658         </programlisting>
1659         </para>
1660         <para>
1661          first. 
1662         </para>
1663         <para>
1664         <programlisting>
1665   autoheader && autoconf && ./configure
1666         </programlisting>
1667         </para>
1668         <para>
1669         Then do
1670         </para>
1671         <para>
1672         <programlisting>
1673   make suse-dist or make redhat-dist
1674         </programlisting>
1675         </para>
1676         <para>
1677         To upload the package to Sourceforge, simply issue
1678         </para>
1679         <para>
1680         <programlisting>
1681   make suse-upload or make redhat-upload
1682         </programlisting>
1683         </para>
1684         <para>
1685         Go to the displayed URL and release the file publicly on Sourceforge.
1686       </para>
1687     </sect2>
1688
1689     <sect2 id="newrelease-os2"><title>OS/2</title>
1690       <para>
1691         Ensure that you have the latest code version. Hence run:
1692         </para>
1693         <para>
1694         <programlisting>
1695   cd current
1696   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
1697   cvs -z3 -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
1698   cd ..
1699   cvs -z3 -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa co os2setup
1700         </programlisting>
1701         </para>
1702         <para>
1703         You will need a mix of development tools.
1704         The main compilation takes place with IBM Visual Age C++.
1705         Some ancillary work takes place with GNU tools, available from
1706         various sources like hobbes.nmsu.edu.
1707         Specificially, you will need <filename>autoheader</filename>,
1708         <filename>autoconf</filename> and <filename>sh</filename> tools.
1709         The packaging takes place with WarpIN, available from various sources, including
1710         its home page: <ulink url="http://www.xworkplace.org/">xworkplace</ulink>.
1711         </para>
1712         <para>
1713         Change directory to the <filename>os2setup</filename> directory.
1714         Edit the os2build.cmd file to set the final executable filename.
1715         For example, 
1716         <programlisting>
1717   installExeName='privoxyos2_setup_X.Y.Z.exe'
1718         </programlisting>
1719         Next, edit the <filename>IJB.wis</filename> file so the release number matches
1720         in the <filename>PACKAGEID</filename> section:
1721         <programlisting>
1722   PACKAGEID="Privoxy Team\Privoxy\Privoxy Package\X\Y\Z"
1723         </programlisting>
1724         You're now ready to build.  Run:
1725         <programlisting>
1726   os2build
1727         </programlisting>
1728      And in the <filename>./files</filename> directory you will have the
1729      WarpIN-installable executable. 
1730      Upload this anonymously to
1731      <filename>uploads.sourceforge.net/incoming</filename>, create a release
1732      for it, and you're done.
1733         </para>
1734     </sect2>
1735
1736     <sect2 id="newrelease-solaris"><title>Solaris</title>
1737       <para>
1738         Login to Sourceforge's compilefarm via ssh
1739         </para>
1740         <para>
1741         <programlisting>
1742   ssh cf.sourceforge.net
1743         </programlisting>
1744         </para>
1745         <para>
1746         Choose the right operating system (not the Debian one). If you have
1747         downloaded <application>Privoxy</application> before,
1748         </para>
1749         <para>
1750         <programlisting>
1751   cd current
1752   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
1753   cvs -z3  -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
1754         </programlisting>
1755         </para>
1756         <para>
1757         If not, please <ulink
1758         url="http://www.privoxy.org/user-manual/user-manual/installation.html#INSTALLATION-SOURCE">checkout
1759         Privoxy via CVS first</ulink>. Run:
1760         </para>
1761         <para>
1762         <programlisting>
1763   autoheader && autoconf && ./configure
1764         </programlisting>
1765         </para>
1766         <para>
1767         Then run
1768         </para>
1769         <para>
1770         <programlisting>
1771   gmake solaris-dist
1772         </programlisting>
1773         </para>
1774         <para>
1775         which creates a gzip'ed tar archive. Sadly, you cannot use <command>make
1776         solaris-upload</command> on the Sourceforge machine (no ncftpput). You now have
1777         to manually upload the archive to Sourceforge's ftp server and release
1778         the file publicly.
1779         </para>
1780     </sect2>
1781
1782     <sect2 id="newrelease-windows"><title>Windows</title>
1783       <para>
1784         Ensure that you have the latest code version. Hence run
1785         </para>
1786         <para>
1787         <programlisting>
1788   cd current
1789   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
1790   cvs -z3  -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
1791         </programlisting>
1792         </para>
1793         <para>
1794          Run:
1795         </para>
1796         <para>
1797         <programlisting>
1798   autoheader && autoconf && ./configure
1799         </programlisting>
1800         </para>
1801         <para>
1802         Then do FIXME.
1803         </para>
1804     </sect2>
1805
1806     <sect2 id="newrelease-debian"><title>Debian</title>
1807       <para>
1808         Ensure that you have the latest code version. Hence run:
1809         </para>
1810         <para>
1811         <programlisting>
1812   cd current
1813   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
1814   cvs -z3  -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
1815         </programlisting>
1816         </para>
1817         <para>
1818         first. Run:
1819         </para>
1820         <para>
1821         <programlisting>
1822   autoheader && autoconf && ./configure
1823         </programlisting>
1824         </para>
1825         <para>
1826         Then do FIXME.
1827         </para>
1828     </sect2>
1829
1830     <sect2 id="newrelease-macosx"><title>Mac OSX</title>
1831       <para>
1832         Ensure that you have the latest code version. Hence run:
1833         </para>
1834         <para>
1835         <programlisting>
1836   cd current
1837   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
1838   cvs -z3 -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
1839   cd ..
1840   cvs -z3 -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa co osxsetup
1841         </programlisting>
1842         </para>
1843         <para>
1844         From the osxsetup directory, run:
1845         <programlisting>
1846   build
1847         </programlisting>
1848         </para>
1849         <para>
1850         This will run <filename>autoheader</filename>, <filename>autoconf</filename> and
1851         <filename>configure</filename> as well as <filename>make</filename>.
1852         Finally, it will copy over the necessary files to the ./osxsetup/files directory
1853         for further processing by <filename>PackageMaker</filename>.
1854         </para>
1855         <para>
1856         Bring up PackageMaker with the PrivoxyPackage.pmsp definition file, modify the package
1857         name to match the release, and hit the "Create package" button.
1858         If you specify ./Privoxy.pkg as the output package name, you can then create
1859         the distributable zip file with the command:
1860         <programlisting>
1861 zip -r privoxyosx_setup_x.y.z.zip Privoxy.pkg
1862         </programlisting>
1863         You can then upload <filename>privoxyosx_setup_x.y.z.zip</filename> anonymously to 
1864         <filename>uploads.sourceforge.net/incoming</filename>,
1865         create a release for it, and you're done.
1866         </para>
1867     </sect2>
1868
1869     <sect2 id="newrelease-freebsd"><title>FreeBSD</title>
1870       <para>
1871         Change the version number of <application>Privoxy</application> in the
1872         configure.in file. Run:
1873         <programlisting>
1874   autoheader && autoconf && ./configure
1875         </programlisting>
1876         Then ...
1877       </para>
1878       <para>
1879         Login to Sourceforge's compilefarm via ssh:
1880         </para>
1881         <para>
1882         <programlisting>
1883   ssh cf.sourceforge.net
1884         </programlisting>
1885         </para>
1886         <para>
1887         Choose the right operating system. If you have downloaded Privoxy
1888         before,
1889         </para>
1890         <para>
1891         <programlisting>
1892   cd current
1893   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
1894   cvs -z3  -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
1895         </programlisting>
1896         </para>
1897         <para>
1898         If not, please <ulink
1899         url="http://www.privoxy.org/user-manual/user-manual/installation.html#INSTALLATION-SOURCE">checkout
1900         Privoxy via CVS first</ulink>. Run:
1901         </para>
1902         <para>
1903         <programlisting>
1904   autoheader && autoconf && ./configure
1905         </programlisting>
1906         </para>
1907         <para>
1908         Then run:
1909         </para>
1910         <para>
1911         <programlisting>
1912   gmake freebsd-dist
1913         </programlisting>
1914         </para>
1915         <para>
1916         which creates a gzip'ed tar archive. Sadly, you cannot use <command>make
1917         freebsd-upload</command> on the Sourceforge machine (no ncftpput). You now have
1918         to manually upload the archive to Sourceforge's ftp server and release
1919         the file publicly.
1920         </para>
1921     </sect2>
1922
1923     <sect2 id="newrelease-tarball"><title>Tarball</title>
1924       <para>
1925         Ensure that you have the latest code version. Hence run:
1926         </para>
1927         <para>
1928         <programlisting>
1929   cd current
1930   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
1931   cvs -z3  -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
1932         </programlisting>
1933         </para>
1934         <para>
1935         first. Run:
1936         </para>
1937         <para>
1938         <programlisting>
1939   make clobber
1940   autoheader && autoconf && ./configure
1941         </programlisting>
1942         </para>
1943         <para>
1944         Then do:
1945         </para>
1946         <para>
1947         <programlisting>
1948   make tarball-dist
1949         </programlisting>
1950         </para>
1951         <para>
1952         To upload the package to Sourceforge, simply issue
1953         </para>
1954         <para>
1955         <programlisting>
1956   make tarball-upload
1957         </programlisting>
1958         </para>
1959         <para>
1960         Goto the displayed URL and release the file publicly on Sourceforge.
1961       </para>
1962     </sect2>
1963
1964     <sect2 id="newrelease-hpux"><title>HP-UX 11</title>
1965       <para>
1966         Ensure that you have the latest code version. Hence run:
1967         </para>
1968         <para>
1969         <programlisting>
1970   cd current
1971   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
1972   cvs -z3  -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
1973         </programlisting>
1974         </para>
1975         <para>
1976         first. Run:
1977         </para>
1978         <para>
1979         <programlisting>
1980   autoheader && autoconf && ./configure
1981         </programlisting>
1982         </para>
1983         <para>
1984         Then do FIXME.
1985         </para>
1986     </sect2>
1987
1988     <sect2 id="newrelease-amiga"><title>Amiga OS</title>
1989       <para>
1990         Ensure that you have the latest code version. Hence run:
1991         </para>
1992         <para>
1993         <programlisting>
1994   cd current
1995   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
1996   cvs -z3  -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
1997         </programlisting>
1998         </para>
1999         <para>
2000         first. Run:
2001         </para>
2002         <para>
2003         <programlisting>
2004   autoheader && autoconf && ./configure
2005         </programlisting>
2006         </para>
2007         <para>
2008         Then do FIXME.
2009         </para>
2010     </sect2>
2011
2012     <sect2 id="newrelease-aix"><title>AIX</title>
2013       <para>
2014         Login to Sourceforge's compilefarm via ssh:
2015         </para>
2016         <para>
2017         <programlisting>
2018   ssh cf.sourceforge.net
2019         </programlisting>
2020         </para>
2021         <para>
2022         Choose the right operating system. If you have downloaded Privoxy
2023         before:
2024         </para>
2025         <para>
2026         <programlisting>
2027   cd current
2028   cvs -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa login
2029   cvs -z3  -d:pserver:anonymous@cvs.ijbswa.sourceforge.net:/cvsroot/ijbswa export -r  v_X_Y_Z current
2030         </programlisting>
2031         </para>
2032         <para>
2033         If not, please <ulink
2034         url="http://www.privoxy.org/user-manual/user-manual/installation.html#INSTALLATION-SOURCE">checkout
2035         Privoxy via CVS first</ulink>. Run:
2036         </para>
2037         <para>
2038         <programlisting>
2039   autoheader && autoconf && ./configure
2040         </programlisting>
2041         </para>
2042         <para>
2043         Then run:
2044         </para>
2045         <para>
2046         <programlisting>
2047   make aix-dist
2048         </programlisting>
2049         </para>
2050         <para>
2051         which creates a gzip'ed tar archive. Sadly, you cannot use <command>make
2052         aix-upload</command> on the Sourceforge machine (no ncftpput). You now have
2053         to manually upload the archive to Sourceforge's ftp server and release
2054         the file publicly.
2055         </para>
2056     </sect2>
2057
2058   </sect1>
2059   
2060   <!--   ~~~~~       New section      ~~~~~     -->
2061   <sect1 id="contact"><title>Contact the developers</title>
2062 <!-- Include contacting.sgml  -->
2063  &contacting;
2064 <!-- end contacting -->
2065   </sect1>
2066   
2067   <!--   ~~~~~       New section      ~~~~~     -->
2068   <sect1 id="copyright"><title>Copyright and History</title>
2069
2070 <sect2><title>Copyright</title>
2071 <!-- Include copyright.sgml -->
2072  &copyright;
2073 <!-- end -->
2074 </sect2>
2075
2076 <sect2><title>History</title>
2077 <!-- Include history.sgml -->
2078  &history;
2079 <!-- end -->
2080 </sect2>
2081
2082   </sect1>
2083   
2084   <!--   ~~~~~       New section      ~~~~~     -->
2085   <sect1 id="seealso"><title>See also</title>
2086 <!-- Include seealso.sgml -->
2087  &seealso;
2088 <!-- end  -->
2089
2090   </sect1>
2091
2092   <!--
2093
2094   This program is free software; you can redistribute it 
2095   and/or modify it under the terms of the GNU General
2096   Public License as published by the Free Software
2097   Foundation; either version 2 of the License, or (at
2098   your option) any later version.
2099
2100   This program is distributed in the hope that it will
2101   be useful, but WITHOUT ANY WARRANTY; without even the
2102   implied warranty of MERCHANTABILITY or FITNESS FOR A
2103   PARTICULAR PURPOSE.  See the GNU General Public
2104   License for more details.
2105
2106   The GNU General Public License should be included with
2107   this file.  If not, you can view it at
2108   http://www.gnu.org/copyleft/gpl.html
2109   or write to the Free Software Foundation, Inc., 59
2110   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
2111
2112   $Log: developer-manual.sgml,v $
2113   Revision 1.21  2002/04/04 06:48:37  hal9
2114   Structural changes to allow for conditional inclusion/exclusion of content
2115   based on entity toggles, e.g. 'entity % p-not-stable  "INCLUDE"'. And
2116   definition of internal entities, e.g. 'entity p-version "2.9.13"' that will
2117   eventually be set by Makefile.
2118   More boilerplate text for use across multiple docs.
2119
2120   Revision 1.20  2002/04/04 03:28:27  david__schmidt
2121   Add Mac OSX section
2122
2123   Revision 1.19  2002/04/03 15:09:42  david__schmidt
2124   Add OS/2 build section
2125
2126   Revision 1.18  2002/04/03 03:51:48  hal9
2127   Touch ups.
2128
2129   Revision 1.17  2002/04/03 01:21:17  hal9
2130   Implementing Andreas's suggestions for Release sections.
2131
2132   Revision 1.16  2002/03/31 23:04:40  hal9
2133   Fleshed out the doc section, and added something for an intro so it was not
2134   blank.
2135
2136   Revision 1.15  2002/03/30 22:29:47  swa
2137   wrong make flavour
2138
2139   Revision 1.14  2002/03/30 19:04:08  swa
2140   people release differently. no good.
2141   I want to make parts of the docs only.
2142
2143   Revision 1.13  2002/03/27 01:16:41  hal9
2144   ditto
2145
2146   Revision 1.12  2002/03/27 01:02:51  hal9
2147   Touch up on name change...
2148
2149   Revision 1.11  2002/03/26 22:29:55  swa
2150   we have a new homepage!
2151
2152   Revision 1.10  2002/03/24 12:33:01  swa
2153   more additions.
2154
2155   Revision 1.9  2002/03/24 11:01:05  swa
2156   name change
2157
2158   Revision 1.8  2002/03/23 15:13:11  swa
2159   renamed every reference to the old name with foobar.
2160   fixed "application foobar application" tag, fixed
2161   "the foobar" with "foobar". left junkbustser in cvs
2162   comments and remarks to history untouched.
2163
2164   Revision 1.7  2002/03/11 13:13:27  swa
2165   correct feedback channels
2166
2167   Revision 1.6  2002/02/24 14:25:06  jongfoster
2168   Formatting changes.  Now changing the doctype to DocBook XML 4.1
2169   will work - no other changes are needed.
2170
2171   Revision 1.5  2001/10/31 18:16:51  swa
2172   documentation added: howto generate docs in text and html
2173   format, howto move stuff to the webserver.
2174
2175   Revision 1.4  2001/09/23 10:13:48  swa
2176   upload process established. run make webserver and
2177   the documentation is moved to the webserver. documents
2178   are now linked correctly.
2179
2180   Revision 1.3  2001/09/13 15:27:40  swa
2181   cosmetics
2182
2183   Revision 1.2  2001/09/13 15:20:17  swa
2184   merged standards into developer manual
2185
2186   Revision 1.1  2001/09/12 15:36:41  swa
2187   source files for junkbuster documentation
2188
2189   Revision 1.3  2001/09/10 17:43:59  swa
2190   first proposal of a structure.
2191
2192   Revision 1.2  2001/06/13 14:28:31  swa
2193   docs should have an author.
2194
2195   Revision 1.1  2001/06/13 14:20:37  swa
2196   first import of project's documentation for the webserver.
2197
2198   -->
2199
2200 </article>