libfossil  Artifact Content

Artifact e62fa3d98ae60dc8b72036eaba567218e9a47efc:

Wiki page [HackersGuide] by stephan 2014-11-07 15:09:51.
D 2014-11-07T15:09:51.532
L HackersGuide
P b24c6c723be46dd8c7af00dbae4bbfa29c771bb5
U stephan
W 3735
<h1>Hacker's Guide</h1>

See also: [building], [AmalgamationBuild]

This page primarily contains notes for anyone who's actively hacking on libfossil internals, e.g. changing <tt>fsl_cx</tt>'s structure.

An <em>exceedingly brief</em> intro to the source tree:

  *  The primary "exported" distributable is the [AmalgamationBuild]. The other sources and headers are essentially components for creating that deliverable.
  *  Public headers go in <tt>include/fossil-scm/</tt>. There is at least one pseudo-private header (<tt>fossil-internal.h</tt>) there as well, but that one is under consideration for being moved to...
  *  Private impl files and headers go in <tt>src/</tt>. 
  *  Demo/test apps can be found in <tt>f-apps/</tt>.
  *  The truly adventurous might wand to explore the other various subdirs, like <tt>sql/</tt> (schema files), <tt>cpp/</tt> (one potential C++ binding) and <tt>s2/</tt> (script bindings).
  *  The "native" build platform requires GNU Make 3.81 or higher and the conventional set of Unix-side build tools. Contributions of control files (or READMEs) for other build platforms are of course welcomed.
  *  The overall style is a direct artifact (as it were) of fossil(1), and we ask that all contributors maintain the general overall style. We are <em>not</em> picky about placement of spaces around parenthesis and whatnot, mainly just the overall indentation and <tt>{</tt>bracing<tt>}</tt> styles, as well as the naming style for public symbols (e.g. a prefix of "fsl_" on most symbols). The one notable exception is how APIs are documented: libfossil uses Doxygen style (and Doxygen cannot swallow fossil's native comment style).



<h2>An Introduction to structs...</h2>

All (or almost all) structs in the library are accompanied by other constructs which help ensure (insure?) consistency regarding how library-level structs are to be initialized. The general pattern looks like this:

<nowiki><pre>
struct fsl_foo { ... };
typedef struct fsl_foo fsl_foo;
extern const fsl_foo_empty;
#define fsl_foo_empty_m { ...member initializers... }
</pre></nowiki>

The purpose of the "empty_m" macro is to define a cleanly-initialized const state for that struct. The <tt>fsl_foo_empty</tt> instance is guaranteed to be initialized using <tt>fsl_foo_empty_m</tt>, but both the "empty" and "empty_m" variants are provided because code requires different initializers in different contexts (examples are provided below).

The "_m" suffix denotes "macro", by the way.

All non-opaque structs can and should be initialized in code like this:

<nowiki><pre>
fsl_buffer buf = fsl_buffer_empty;
fsl_deck deck = fsl_deck_empty;

// The "empty_m" macros are required mainly for in-struct initialization:
struct {
  fsl_buffer buf;
  fsl_deck deck;
} foo = {
  fsl_buffer_empty_m,
  fsl_deck_empty_m
};
</pre></nowiki>

That ensures (insures?) that all struct members get set to known default values (which need not be NULL/0), and helps harden the code against uninitialized memory access (since all members get initialized to whatever the struct developer deemed sensible, and NULL is generally the sensible default for pointer members).


<h2>When updating structs...</h2>

When changing the members of structs, it is <em>critical</em> that the accompanying "empty_m" macro (described above) also be updated. Failing to do so can lead to undefined results (best case is a compilation failure when the shared struct "empty" instance is initialized from the "empty_m" macro).

After changing a struct, make sure to do a full/clean rebuild or you might see <em>really</em> weird results in code compiled against older struct.

<nowiki><pre>
</pre></nowiki>
Z d5b75c74f3db57cf09ff914a73c4b9ae