1 | <html> |
---|
2 | <head> |
---|
3 | <title>libsm Overview</title> |
---|
4 | </head> |
---|
5 | <body> |
---|
6 | |
---|
7 | <center> |
---|
8 | <h1> libsm Overview </h1> |
---|
9 | <br> $Id: index.html,v 1.1.1.1 2003-04-08 15:11:54 zacheiss Exp $ |
---|
10 | </center> |
---|
11 | |
---|
12 | <h2> Introduction </h2> |
---|
13 | |
---|
14 | Libsm is a library of generally useful C abstractions. |
---|
15 | Libsm stands alone; it depends on no other sendmail libraries, |
---|
16 | and the only sendmail header files it depends on are its own, |
---|
17 | which reside in <tt>../include/sm</tt>. |
---|
18 | |
---|
19 | <h2> Contents </h2> |
---|
20 | |
---|
21 | Here is the current set of packages: |
---|
22 | <blockquote> |
---|
23 | <a href="gen.html"> gen: general definitions </a><br> |
---|
24 | <a href="debug.html"> debug: debugging and tracing </a><br> |
---|
25 | <a href="assert.html"> assert: assertion handling and aborts </a><br> |
---|
26 | <a href="heap.html"> heap: memory allocation </a><br> |
---|
27 | <a href="exc.html"> exc: exception handling </a><br> |
---|
28 | <a href="rpool.html"> rpool: resource pools </a><br> |
---|
29 | <a href="cdefs.html"> cdefs: C language portability macros </a><br> |
---|
30 | <a href="io.html"> io: buffered i/o </a><br> |
---|
31 | </blockquote> |
---|
32 | |
---|
33 | <h2> Naming Conventions </h2> |
---|
34 | |
---|
35 | Some of the symbols defined by libsm |
---|
36 | come from widely used defacto or dejure standards. |
---|
37 | Examples include <tt>size_t</tt> (from the C 89 standard), |
---|
38 | <tt>bool</tt> (from the C 99 standard), |
---|
39 | <tt>strerror</tt> (from Posix), |
---|
40 | and <tt>__P</tt> (from BSD and Linux). |
---|
41 | In these cases, we use the standard name rather than |
---|
42 | inventing a new name. |
---|
43 | We import the name from the appropriate header file when possible, |
---|
44 | or define it ourselves when necessary. |
---|
45 | When you are using one of these abstractions, you must include |
---|
46 | the appropriate libsm header file. |
---|
47 | For example, when you are using <tt>strerror</tt>, you must |
---|
48 | include <tt><sm/string.h></tt> instead of <tt><string.h></tt>. |
---|
49 | |
---|
50 | <p> |
---|
51 | When we aren't implementing a standard interface, |
---|
52 | we use a naming convention that attempts to maximize portability |
---|
53 | across platforms, and minimize conflicts with other libraries. |
---|
54 | Except for a few seemingly benign exceptions, |
---|
55 | all names begin with <tt>SM_</tt>, <tt>Sm</tt> or <tt>sm_</tt>. |
---|
56 | |
---|
57 | <p> |
---|
58 | The ISO C, Posix and Unix standards forbid applications |
---|
59 | from using names beginning with <tt>__</tt> or <tt>_[A-Z]</tt>, |
---|
60 | and place restrictions on what sorts of names can begin |
---|
61 | with <tt>_[a-z]</tt>. Such names are reserved for the compiler and |
---|
62 | the standard libraries. |
---|
63 | For this reason, we avoid defining any names that begin |
---|
64 | with <tt>_</tt>. |
---|
65 | For example, all libsm header file idempotency macros have the form |
---|
66 | <tt>SM_FOO_H</tt> (no leading <tt>_</tt>). |
---|
67 | |
---|
68 | <p> |
---|
69 | Type names begin with <tt>SM_</tt> and end with <tt>_T</tt>. |
---|
70 | Note that the Posix standard reserves all identifiers ending |
---|
71 | with <tt>_t</tt>. |
---|
72 | |
---|
73 | <p> |
---|
74 | All functions that are capable of raising an exception |
---|
75 | have names ending in <tt>_x</tt>, and developers are |
---|
76 | encouraged to use this convention when writing new code. |
---|
77 | This naming convention may seem unnecessary at first, |
---|
78 | but it becomes extremely useful during maintenance, |
---|
79 | when you are attempting to reason about the correctness |
---|
80 | of a block of code, |
---|
81 | and when you are trying to track down exception-related bugs |
---|
82 | in existing code. |
---|
83 | |
---|
84 | <h2> Coding Conventions </h2> |
---|
85 | |
---|
86 | The official style for function prototypes in libsm header files is |
---|
87 | |
---|
88 | <blockquote><pre> |
---|
89 | extern int |
---|
90 | foo __P(( |
---|
91 | int _firstarg, |
---|
92 | int _secondarg)); |
---|
93 | </pre></blockquote> |
---|
94 | |
---|
95 | The <tt>extern</tt> is useless, but required for stylistic reasons. |
---|
96 | The parameter names are optional; if present they are lowercase |
---|
97 | and begin with _ to avoid namespace conflicts. |
---|
98 | Each parameter is written on its own line to avoid very long lines. |
---|
99 | |
---|
100 | <p> |
---|
101 | For each structure <tt>struct sm_foo</tt> defined by libsm, |
---|
102 | there is a typedef: |
---|
103 | |
---|
104 | <blockquote><pre> |
---|
105 | typedef struct sm_foo SM_FOO_T; |
---|
106 | </pre></blockquote> |
---|
107 | |
---|
108 | and there is a global variable which is defined as follows: |
---|
109 | |
---|
110 | <blockquote><pre> |
---|
111 | const char SmFooMagic[] = "sm_foo"; |
---|
112 | </pre></blockquote> |
---|
113 | |
---|
114 | The first member of each structure defined by libsm is |
---|
115 | |
---|
116 | <blockquote><pre> |
---|
117 | const char *sm_magic; |
---|
118 | </pre></blockquote> |
---|
119 | |
---|
120 | For all instances of <tt>struct sm_foo</tt>, |
---|
121 | <tt>sm_magic</tt> contains <tt>SmFooMagic</tt>, |
---|
122 | which points to a unique character string naming the type. |
---|
123 | It is used for debugging and run time type checking. |
---|
124 | |
---|
125 | <p> |
---|
126 | Each function with a parameter declared <tt>SM_FOO_T *foo</tt> |
---|
127 | contains the following assertion: |
---|
128 | |
---|
129 | <blockquote><pre> |
---|
130 | SM_REQUIRE_ISA(foo, SmFooMagic); |
---|
131 | </pre></blockquote> |
---|
132 | |
---|
133 | which is equivalent to |
---|
134 | |
---|
135 | <blockquote><pre> |
---|
136 | SM_REQUIRE(foo != NULL && foo->sm_magic == SmFooMagic); |
---|
137 | </pre></blockquote> |
---|
138 | |
---|
139 | When an object of type <tt>SM_FOO_T</tt> is deallocated, |
---|
140 | the member <tt>sm_magic</tt> is set to <tt>NULL</tt>. |
---|
141 | That will cause the above assertion to fail if a dangling pointer is used. |
---|
142 | |
---|
143 | <h2> Additional Design Goals </h2> |
---|
144 | |
---|
145 | Here are some of my design goals: |
---|
146 | <ul> |
---|
147 | <p> |
---|
148 | <li>The sm library is self contained; it does not depend on any other |
---|
149 | sendmail libraries or header files. |
---|
150 | <p> |
---|
151 | <li>The sm library must be compatible with shared libraries, |
---|
152 | even on platforms with weird implementation restrictions. |
---|
153 | I assume that a shared library can export global variables; |
---|
154 | the debug package relies on this assumption. |
---|
155 | I do not assume that if an application redefines a function defined |
---|
156 | in a shared library, the shared library will use the version of the |
---|
157 | function defined in the application in preference to the version |
---|
158 | that it defines. |
---|
159 | For this reason, I provide interfaces for registering handler functions |
---|
160 | in cases where an application might need to override standard behaviour. |
---|
161 | <p> |
---|
162 | <li>The sm library must be compatible with threads. |
---|
163 | The debug package presents a small problem: I don't want |
---|
164 | sm_debug_active to acquire and release a lock. |
---|
165 | So I assume that |
---|
166 | there exists an integral type <tt>SM_ATOMIC_INT_T</tt> |
---|
167 | (see <a href="gen.html"><tt><sm/gen.h></tt></a>) |
---|
168 | that can be accessed and updated atomically. |
---|
169 | I assume that locking must be used to guard updates and accesses to |
---|
170 | any other type, and I have designed the interfaces accordingly. |
---|
171 | </ul> |
---|
172 | |
---|
173 | </body> |
---|
174 | </html> |
---|