190792Sgshapiro<html> 290792Sgshapiro<head> 390792Sgshapiro <title>libsm Overview</title> 490792Sgshapiro</head> 590792Sgshapiro<body> 690792Sgshapiro 790792Sgshapiro<center> 890792Sgshapiro <h1> libsm Overview </h1> 9266692Sgshapiro <br> $Id: index.html,v 1.14 2001-02-13 21:21:25 gshapiro Exp $ 1090792Sgshapiro</center> 1190792Sgshapiro 1290792Sgshapiro<h2> Introduction </h2> 1390792Sgshapiro 1490792SgshapiroLibsm is a library of generally useful C abstractions. 1590792SgshapiroLibsm stands alone; it depends on no other sendmail libraries, 1690792Sgshapiroand the only sendmail header files it depends on are its own, 1790792Sgshapirowhich reside in <tt>../include/sm</tt>. 1890792Sgshapiro 1990792Sgshapiro<h2> Contents </h2> 2090792Sgshapiro 2190792SgshapiroHere is the current set of packages: 2290792Sgshapiro<blockquote> 2390792Sgshapiro <a href="gen.html"> gen: general definitions </a><br> 2490792Sgshapiro <a href="debug.html"> debug: debugging and tracing </a><br> 2590792Sgshapiro <a href="assert.html"> assert: assertion handling and aborts </a><br> 2690792Sgshapiro <a href="heap.html"> heap: memory allocation </a><br> 2790792Sgshapiro <a href="exc.html"> exc: exception handling </a><br> 2890792Sgshapiro <a href="rpool.html"> rpool: resource pools </a><br> 2990792Sgshapiro <a href="cdefs.html"> cdefs: C language portability macros </a><br> 3090792Sgshapiro <a href="io.html"> io: buffered i/o </a><br> 3190792Sgshapiro</blockquote> 3290792Sgshapiro 3390792Sgshapiro<h2> Naming Conventions </h2> 3490792Sgshapiro 3590792Sgshapiro Some of the symbols defined by libsm 3690792Sgshapiro come from widely used defacto or dejure standards. 3790792Sgshapiro Examples include <tt>size_t</tt> (from the C 89 standard), 3890792Sgshapiro <tt>bool</tt> (from the C 99 standard), 3990792Sgshapiro <tt>strerror</tt> (from Posix), 4090792Sgshapiro and <tt>__P</tt> (from BSD and Linux). 4190792Sgshapiro In these cases, we use the standard name rather than 4290792Sgshapiro inventing a new name. 4390792Sgshapiro We import the name from the appropriate header file when possible, 4490792Sgshapiro or define it ourselves when necessary. 4590792Sgshapiro When you are using one of these abstractions, you must include 4690792Sgshapiro the appropriate libsm header file. 4790792Sgshapiro For example, when you are using <tt>strerror</tt>, you must 4890792Sgshapiro include <tt><sm/string.h></tt> instead of <tt><string.h></tt>. 4990792Sgshapiro 5090792Sgshapiro <p> 5190792Sgshapiro When we aren't implementing a standard interface, 5290792Sgshapiro we use a naming convention that attempts to maximize portability 5390792Sgshapiro across platforms, and minimize conflicts with other libraries. 5490792Sgshapiro Except for a few seemingly benign exceptions, 5590792Sgshapiro all names begin with <tt>SM_</tt>, <tt>Sm</tt> or <tt>sm_</tt>. 5690792Sgshapiro 5790792Sgshapiro <p> 5890792Sgshapiro The ISO C, Posix and Unix standards forbid applications 5990792Sgshapiro from using names beginning with <tt>__</tt> or <tt>_[A-Z]</tt>, 6090792Sgshapiro and place restrictions on what sorts of names can begin 6190792Sgshapiro with <tt>_[a-z]</tt>. Such names are reserved for the compiler and 6290792Sgshapiro the standard libraries. 6390792Sgshapiro For this reason, we avoid defining any names that begin 6490792Sgshapiro with <tt>_</tt>. 6590792Sgshapiro For example, all libsm header file idempotency macros have the form 6690792Sgshapiro <tt>SM_FOO_H</tt> (no leading <tt>_</tt>). 6790792Sgshapiro 6890792Sgshapiro <p> 6990792Sgshapiro Type names begin with <tt>SM_</tt> and end with <tt>_T</tt>. 7090792Sgshapiro Note that the Posix standard reserves all identifiers ending 7190792Sgshapiro with <tt>_t</tt>. 7290792Sgshapiro 7390792Sgshapiro <p> 7490792Sgshapiro All functions that are capable of raising an exception 7590792Sgshapiro have names ending in <tt>_x</tt>, and developers are 7690792Sgshapiro encouraged to use this convention when writing new code. 7790792Sgshapiro This naming convention may seem unnecessary at first, 7890792Sgshapiro but it becomes extremely useful during maintenance, 7990792Sgshapiro when you are attempting to reason about the correctness 8090792Sgshapiro of a block of code, 8190792Sgshapiro and when you are trying to track down exception-related bugs 8290792Sgshapiro in existing code. 8390792Sgshapiro 8490792Sgshapiro<h2> Coding Conventions </h2> 8590792Sgshapiro 8690792SgshapiroThe official style for function prototypes in libsm header files is 8790792Sgshapiro 8890792Sgshapiro<blockquote><pre> 8990792Sgshapiroextern int 9090792Sgshapirofoo __P(( 9190792Sgshapiro int _firstarg, 9290792Sgshapiro int _secondarg)); 9390792Sgshapiro</pre></blockquote> 9490792Sgshapiro 9590792SgshapiroThe <tt>extern</tt> is useless, but required for stylistic reasons. 9690792SgshapiroThe parameter names are optional; if present they are lowercase 9790792Sgshapiroand begin with _ to avoid namespace conflicts. 9890792SgshapiroEach parameter is written on its own line to avoid very long lines. 9990792Sgshapiro 10090792Sgshapiro<p> 10190792SgshapiroFor each structure <tt>struct sm_foo</tt> defined by libsm, 10290792Sgshapirothere is a typedef: 10390792Sgshapiro 10490792Sgshapiro<blockquote><pre> 10590792Sgshapirotypedef struct sm_foo SM_FOO_T; 10690792Sgshapiro</pre></blockquote> 10790792Sgshapiro 10890792Sgshapiroand there is a global variable which is defined as follows: 10990792Sgshapiro 11090792Sgshapiro<blockquote><pre> 11190792Sgshapiroconst char SmFooMagic[] = "sm_foo"; 11290792Sgshapiro</pre></blockquote> 11390792Sgshapiro 11490792SgshapiroThe first member of each structure defined by libsm is 11590792Sgshapiro 11690792Sgshapiro<blockquote><pre> 11790792Sgshapiroconst char *sm_magic; 11890792Sgshapiro</pre></blockquote> 11990792Sgshapiro 12090792SgshapiroFor all instances of <tt>struct sm_foo</tt>, 12190792Sgshapiro<tt>sm_magic</tt> contains <tt>SmFooMagic</tt>, 12290792Sgshapirowhich points to a unique character string naming the type. 12390792SgshapiroIt is used for debugging and run time type checking. 12490792Sgshapiro 12590792Sgshapiro<p> 12690792SgshapiroEach function with a parameter declared <tt>SM_FOO_T *foo</tt> 12790792Sgshapirocontains the following assertion: 12890792Sgshapiro 12990792Sgshapiro<blockquote><pre> 13090792SgshapiroSM_REQUIRE_ISA(foo, SmFooMagic); 13190792Sgshapiro</pre></blockquote> 13290792Sgshapiro 13390792Sgshapirowhich is equivalent to 13490792Sgshapiro 13590792Sgshapiro<blockquote><pre> 13690792SgshapiroSM_REQUIRE(foo != NULL && foo->sm_magic == SmFooMagic); 13790792Sgshapiro</pre></blockquote> 13890792Sgshapiro 13990792SgshapiroWhen an object of type <tt>SM_FOO_T</tt> is deallocated, 14090792Sgshapirothe member <tt>sm_magic</tt> is set to <tt>NULL</tt>. 14190792SgshapiroThat will cause the above assertion to fail if a dangling pointer is used. 14290792Sgshapiro 14390792Sgshapiro<h2> Additional Design Goals </h2> 14490792Sgshapiro 14590792SgshapiroHere are some of my design goals: 14690792Sgshapiro<ul> 14790792Sgshapiro <p> 14890792Sgshapiro<li>The sm library is self contained; it does not depend on any other 14990792Sgshapiro sendmail libraries or header files. 15090792Sgshapiro <p> 15190792Sgshapiro<li>The sm library must be compatible with shared libraries, 15290792Sgshapiro even on platforms with weird implementation restrictions. 15390792Sgshapiro I assume that a shared library can export global variables; 15490792Sgshapiro the debug package relies on this assumption. 15590792Sgshapiro I do not assume that if an application redefines a function defined 15690792Sgshapiro in a shared library, the shared library will use the version of the 15790792Sgshapiro function defined in the application in preference to the version 15890792Sgshapiro that it defines. 15990792Sgshapiro For this reason, I provide interfaces for registering handler functions 16090792Sgshapiro in cases where an application might need to override standard behaviour. 16190792Sgshapiro <p> 16290792Sgshapiro<li>The sm library must be compatible with threads. 16390792Sgshapiro The debug package presents a small problem: I don't want 16490792Sgshapiro sm_debug_active to acquire and release a lock. 16590792Sgshapiro So I assume that 16690792Sgshapiro there exists an integral type <tt>SM_ATOMIC_INT_T</tt> 16790792Sgshapiro (see <a href="gen.html"><tt><sm/gen.h></tt></a>) 16890792Sgshapiro that can be accessed and updated atomically. 16990792Sgshapiro I assume that locking must be used to guard updates and accesses to 17090792Sgshapiro any other type, and I have designed the interfaces accordingly. 17190792Sgshapiro</ul> 17290792Sgshapiro 17390792Sgshapiro</body> 17490792Sgshapiro</html> 175