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