These are more like observations from a latecomer, but better than nothing. CvstracArchitecture is a big picture overview. This talks about the nitty-gritty coding details.
Indentation
CVSTrac source uses two spaces for indentation, no tabs.
Braces and Parentheses
Braces are a modified K&R. Generally, there should be no whitespace between the trailing paren and the leading brace. i.e.
void function(args){ if( condition ){ } }
In the case of else and else if keywords, also eliminate extra whitespace:
if( condition ){ }else if( condition2 ){ }else{ }
Within parentheses, rules differ. For example, if and while statements use internal whitespace:
if( condition ){ while( v[i] ) i++; }
but for loops are a bit different:
for(i=0; i<40; i++){ }
Note that single-line if, for and occasionally while constructs are perfectly acceptable:
if( tn<=0 ) tn = 1; for(nChng=0; az[nChng]; nChng++){}
Preprocessing
CVSTrac has a magical preprocessor which extracts HTML strings prefixed inline by '@' characters and basically turns them into cgi_printf() calls. CvstracArchitecture discusses this further.
Variables
Variable naming is partially Hungarian style.
- 'z' prefixes NUL-terminated strings
- 'az' prefixes an array of 'z' strings. 'az' strings also appear to be NULL terminated.
- 'p' prefixes a pointer to something
- 'n' occasionally prefixes integers
Some commonly used variable names
tn
is a ticket numbercn
is a change/checkin numberrn
is a report number
Frequently Seen Functions
Not even close to a complete list.
P(x)
the CGI parameter x, orNULL
PD(x,y)
the CGI parameter x, or ycgi_printf()
writes a formatted string into the CGI output buffermprintf()
is a custom function to format a string into a new memory bufferoutput_formatted(zText,zPage)
output zText to the CGI buffer, doing any needed wiki formatting. zPage indicates the source page (i.e. wiki page) and is used for finding embeddable attachments like images.db_query()
execute a SQLite query against the database and return the results as an az array. Deallocate results withdb_query_free()
.db_short_query()
, returns a single NUL-terminated string. Clean up withfree()
.db_execute()
executes a SQLite query, returning nothing.OS_VAL(unix,win)
expands to unix under non-Windows builds and to win under Windows builds. Used to select platform dependent constants and expressions.
Memory
CVSTrac doesn't worry about memory management! It's assumed that a CVSTrac instance will live only long enough to serve out a request and then resources will be reclaimed (AKA garbage collection by exit()). As such, you frequently see constructs like:
zPath = mprintf("%s/%s", zDir, zFile);
without a corresponding free(). The only time memory is really a concern happens when a large amount of activity happens in a loop. In such instances, free() or db_query_free() will be used.
Format Strings
CVSTrac uses a custom mprintf() which supports additional formatting. For security purposes, the following are preferred over just %s:
- %h Escapes HTML markup
- %T For URLs. Preserves "/" characters
- %t For URLs. Translates "/" into "%2F"
- %q Escapes ' characters in SQL
Security
CVSTrac cares about security. This means dynamic memory allocation where possible, really large static buffers with limits on the size of copies, heavy use of the %q format (as found in mprintf() and db_query()), and a lot of heavily used helper functions to manage all this.
Platform Dependent Code
Platform dependent code is generally caused Windows API incompatibility with general UNIX (POSIX) specification and Windows command line and shell command line differences. Where it is possible Windows code parts are distinguished with OS_VAL
macro.
Where it is not possible, #ifdef CVSTRAC_WINDOWS
preprocessor conditional block is used (CVSTRAC_WINDOWS
is defined within the code in Windows) and appropriate comment regarding the difference is provided.