# Architecture of the CVSTrac Program

## 1.0 Introduction

This note gives a high-level overview of how the CVSTrac program works and how it is put together. It is assumed that the reader is already familiar with what CVSTrac does. The purpose of this document is to provide some additional background information on the internal operation of CVSTrac in order to guide potential contributors in making improvements to the code.

## 2.0 Design Rules

CVSTrac is designed so that each incoming HTTP request is handled by a separate process. No attempt is made to avoid memory leaks, since the process will terminate as soon as the HTTP request is finished. Global variables are used where it is convenient since only a single thread will be running in the address space.

Some people have worried that using a separate process for each HTTP request is inefficient. It may be true that one process per request is not the most efficient design, but it appears to be efficient enough. A 166MHz Pentium with 32MB of RAM has proven to be more than adequate to service a large development group. So for now, CVSTrac will stick with a simple but adequate design that avoids subtle bugs rather than push the envelope with a high-performance design that is harder to work with and more prone to errors.

The program is designed for Unix. No thought has been given to making it run on the "other platform", though there have been reports of success getting it to work using Cygwin.

## 3.0 Code Generators And Preprocessors

The programming language is C. But most of the code that actually reaches the C compiler is either automatically generated or preprocessed. The source code that you, the programmer, look at in an editor is not the same source code that the C compiler works with.

CVSTrac currently uses five different code generators and preprocessors:

- Most of the header files (the *.h files) are generated by the makeheaders program.

- The C source files contain embedded HTML text. This text is converted into special function calls using the "`translate`" preprocessor.

- Each CVSTrac webpage is handled by a different subroutine. The page handler subroutine each have a special header comment that identifies them as such. The `mkindex` program scans the source files for these header comments and constructs a table of webpages used by by the dispatcher.

- The text of the initial wiki that are created when a new project is initialized is contained in the "`wikiinit.c`" source file. That source file is created by editing the wiki in a working CVSTrac project, then running the "`makewikiinit`" program over the project database.

- The "`main.mk`" makefile is generated by a Tcl script "`makemake.tcl`".

A few of these code generators and preprocessors are explained in added detail by the following subheadings.

### 3.1 Extracting embedded HTML using `translate`

The CVSTrac program deals with a lot of text - mostly HTML but also a fair amount of SQL. But large blocks of text (where large means hundreds or thousands of characters or dozens of lines) are difficult to deal with in C. All the text must be enclosed in double-quotes and special characters, such as newlines and the double-quote character itself, must be escaped by using a backslash. The net result is that the text becomes difficult to read and edit.

The `translate` program tries to make the code more readable by converting all lines that begin with a "`@`" character into code that appends the text on that line to the HTML document being generated. This makes the output text more readable by avoiding the need to write "`\n`" and "`\"`". Furthermore, the line of `@` at the left margin allows the eye to quickly see what code is C executable and what is HTML text. Consider this example (taken from `ticket.c`):

>       @
>       @ Description:
>       @ (<small>See <a href="#format_hints">formatting hints</a></small>)<br>
>       if( isPreview ){
>         @ <table border=1 cellpadding=15 width="100%%"><tr><td>
>         output_formatted(aParm[10].zNew);
>         @  </td></tr></table><br>
>         @ <input type="hidden" name="c" value="%h(aParm[10].zNew)">
>       }else{
>         @ <textarea name="c" rows="8" cols="70" wrap="virtual">
>         @ %h(aParm[10].zNew)
>         @ </textarea><br>
>       }

This is a block of code that generates the "Description:" section of a ticket display in CVSTrac. The text of the description will appear formatted as HTML if the "isPreview" boolean is true or as an editable textarea if "isPreview" is false.

The embedded HTML text can contain references to C variables. For example, "`%s(z)`" will insert the content of the string variable "z". "`%d(n)`" will insert the content of integer n. The "`%`" character is generated by putting two percent signs in a row, like this: "`%%`". Of special note is the sequence "`%h(z)`" which inserts the content of string variable z, but also translates that content by escaping characters that have special meaning to HTML. So if you write code like this:

>       z = " & ";
>       @ The string is: %h(z)

The generated HTML will look like this:

>     The string is &lt;yes&gt; &amp; &lt;no&gt;

The `%h` substitution is used extensively in CVSTrac to make user-entered text safe for inclusing in an HTML document.

From this short example, it may not be immediately clear that the `translate` program helps the readability of the code. But if you examine a larger section of the source and compare it to the real C code that `translate` outputs, you will find that the code with embedded HTML is much easier to work with.

Additional information about `translate` can be found in the header comments of the program's source file: `translate.c`.

To be continued...