1 /*
2 * Copyright (C) 1997-2004, Michael Jennings
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies of the Software, its documentation and marketing & publicity
13 * materials, and acknowledgment shall be given in the documentation, materials
14 * and software packages that this Software was used.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * @file obj.c
26 * LibAST Object Infrastructure -- Generic Objects
27 *
28 * This file contains the basic object class.
29 *
30 * @author Michael Jennings <mej@eterm.org>
31 * $Revision: 1.27 $
32 * $Date: 2004/07/23 21:38:39 $
33 */
34
35 static const char __attribute__((unused)) cvs_ident[] = "$Id: obj.c,v 1.27 2004/07/23 21:38:39 mej Exp $";
36
37 #ifdef HAVE_CONFIG_H
38 # include <config.h>
39 #endif
40
41 #include <libast_internal.h>
42
43 /* *INDENT-OFF* */
44 /**
45 * The actual class structure for the @c obj type.
46 *
47 * This structure is the actual class for the @c obj type. All LibAST
48 * objects contain a spif_class_t member called @c cls which points to
49 * a class structure, like this one. The first structure member is a
50 * pointer to the class name. Each class uses the same pointer, so
51 * you can compare the pointer values rather than having to compare
52 * strings. All other members are function pointers which reference
53 * the object-agnostic routines that object supports. ALL LibAST
54 * objects support at least 8 operations: new, init, done, del, show,
55 * comp, dup, and type. Other classes may define other standard
56 * functions. (This is used for doing interface classes.)
57 *
58 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink
59 * @ingroup DOXGRP_OBJ
60 */
61 static SPIF_CONST_TYPE(class) o_class = {
62 SPIF_DECL_CLASSNAME(obj),
63 (spif_func_t) spif_obj_new,
64 (spif_func_t) spif_obj_init,
65 (spif_func_t) spif_obj_done,
66 (spif_func_t) spif_obj_del,
67 (spif_func_t) spif_obj_show,
68 (spif_func_t) spif_obj_comp,
69 (spif_func_t) spif_obj_dup,
70 (spif_func_t) spif_obj_type
71 };
72
73 /**
74 * The class instance for the @c obj type.
75 *
76 * This defines the spif_class_t for the @c obj type so that it points
77 * to the spif_const_class_t structure above. This pointer value is
78 * the very first thing stored in each * instance of an "obj."
79 *
80 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink
81 * @ingroup DOXGRP_OBJ
82 */
83 SPIF_TYPE(class) SPIF_CLASS_VAR(obj) = &o_class;
84 /* *INDENT-ON* */
85
86
87
88 /*@{*/
89 /**
90 * @name Generic Object Member Functions
91 * ---
92 *
93 * These functions are members of the @c obj class. They can be
94 * called directly or via the macros which dereference the function
95 * pointers in the @c obj class structure. By convention, functions
96 * are called directly when the object type is known and via macros
97 * when the type is unknown.
98 *
99 * Most of these functions are not intended to actually be called.
100 * Rather, they serve as models for the implementation of standard
101 * methods in other (derived) object types.
102 *
103 * @ingroup DOXGRP_OBJ
104 */
105
106 /**
107 * Create a new @c obj instance.
108 *
109 * This function creates and returns a new instance of an @c obj. The
110 * new instance is initialized using the spif_obj_init() function.
111 *
112 * @return A new @c obj instance.
113 *
114 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink
115 */
116 spif_obj_t
spif_obj_new(void)117 spif_obj_new(void)
118 {
119 spif_obj_t self;
120
121 self = SPIF_ALLOC(obj);
122 if (!spif_obj_init(self)) {
123 SPIF_DEALLOC(self);
124 self = SPIF_NULL_TYPE(obj);
125 }
126 return self;
127 }
128
129 /**
130 * Delete an @c obj instance.
131 *
132 * This function deletes an instance of an @c obj. The done method,
133 * spif_obj_done(), is called to free any object resources prior to
134 * deallocation of the object itself.
135 *
136 * @param self The @c obj instance to be deleted.
137 * @return #TRUE if successful, #FALSE otherwise.
138 *
139 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink
140 * @ingroup DOXGRP_OBJ
141 */
142 spif_bool_t
spif_obj_del(spif_obj_t self)143 spif_obj_del(spif_obj_t self)
144 {
145 spif_bool_t t;
146
147 ASSERT_RVAL(!SPIF_OBJ_ISNULL(self), FALSE);
148
149 t = spif_obj_done(self);
150 SPIF_DEALLOC(self);
151 return t;
152 }
153
154 /**
155 * Initialize an @c obj instance.
156 *
157 * This function initializes the member variables of the @c obj
158 * instance to their appropriate "bootstrap" values.
159 *
160 * @note Though the calling of the parent's initializer is customary
161 * and proper in derived classes, for subtypes of @c obj, this is not
162 * strictly necessary. All this function does is set the class to
163 * that of an @c obj, which the child must undo anyway (by calling
164 * <tt>spif_obj_set_class(self, SPIF_CLASS_VAR(XXX))</tt>, where
165 * <tt>XXX</tt> is the class name, like below). Thus, it is
166 * acceptable for direct decendents of @c obj to not call this
167 * function. However, anything whose parent type is @a not @c obj
168 * MUST call their parent's init function.
169 *
170 * @param self The @c obj instance to be initialized.
171 * @return #TRUE if successful, #FALSE otherwise.
172 *
173 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink
174 * @ingroup DOXGRP_OBJ
175 */
176 spif_bool_t
spif_obj_init(spif_obj_t self)177 spif_obj_init(spif_obj_t self)
178 {
179 ASSERT_RVAL(!SPIF_OBJ_ISNULL(self), FALSE);
180 spif_obj_set_class(self, SPIF_CLASS_VAR(obj));
181 return TRUE;
182 }
183
184 /**
185 * Deallocate and reinitialize @c obj resources.
186 *
187 * This function frees up any object resources and re-initializes them
188 * to their "bootstrap" values.
189 *
190 * @param self The @c obj instance to be zeroed and reinitialized.
191 * @return #TRUE if successful, #FALSE otherwise.
192 *
193 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink
194 * @ingroup DOXGRP_OBJ
195 */
196 spif_bool_t
spif_obj_done(spif_obj_t self)197 spif_obj_done(spif_obj_t self)
198 {
199 ASSERT_RVAL(!SPIF_OBJ_ISNULL(self), FALSE);
200 return TRUE;
201 }
202
203 /**
204 * Show an object and its contents.
205 *
206 * This function, as it is written here, doesn't do a whole hell of a
207 * lot. But this standard member function (i.e., all objects must
208 * have one) provides the mechanism for which an object can display
209 * not only itself and its particular values, but those of any parent
210 * class or member object. Besides the object to be displayed, this
211 * function is passed the variable name for that object (usually a
212 * constant string, like "foo"), a @c str object, possibly NULL, to be
213 * added to and returned, and an indent level, possibly 0, to
214 * represent how many leading spaces should pad the resulting output.
215 * The @c str object returned is either @a buff, or a new @c str if @a
216 * buff was passed as NULL. Appended to it will be the description of
217 * the object followed by a newline. This description may include
218 * descriptions of any number of child variables, parent objects, etc.
219 *
220 * Implementing this function properly is key to simplifying the
221 * examination of objects through the use of debugging code. I @b
222 * highly recommend looking at some examples of how this function
223 * should be implemented.
224 *
225 * The simplest way to display an object is to use the SPIF_SHOW()
226 * macro. This macro takes the object (@a self) and a file descriptor
227 * (like @c stderr or #LIBAST_DEBUG_FD), calls the object's @c show
228 * method, and prints the resulting string on the given file
229 * descriptor, freeing it afterward. No muss, no fuss.
230 *
231 * @param self The @c obj instance.
232 * @param name The name of the variable passed as @a self.
233 * @param buff A @c str object, possibly NULL, used as the buffer.
234 * @param indent The number of spaces with which to pad the line.
235 * @return The @c str object, or a new one if @a buff was NULL,
236 * describing @a self.
237 *
238 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink, SPIF_SHOW()
239 * @ingroup DOXGRP_OBJ
240 */
241 spif_str_t
spif_obj_show(spif_obj_t self,spif_charptr_t name,spif_str_t buff,size_t indent)242 spif_obj_show(spif_obj_t self, spif_charptr_t name, spif_str_t buff, size_t indent)
243 {
244 spif_char_t tmp[4096];
245
246 if (SPIF_OBJ_ISNULL(self)) {
247 SPIF_OBJ_SHOW_NULL(obj, name, buff, indent, tmp);
248 return buff;
249 }
250
251 memset(tmp, ' ', indent);
252 snprintf(SPIF_CAST_C(char *) tmp + indent, sizeof(tmp) - indent,
253 "(spif_obj_t) %s: %10p \"%s\"\n",
254 name, SPIF_CAST(ptr) self, SPIF_OBJ_CLASSNAME(self));
255 if (SPIF_STR_ISNULL(buff)) {
256 buff = spif_str_new_from_ptr(tmp);
257 } else {
258 spif_str_append_from_ptr(buff, tmp);
259 }
260 return buff;
261 }
262
263 /**
264 * Compare two objects.
265 *
266 * As with most of the other member functions of the @c obj class,
267 * this one is really just a placeholder. The @c comp standard member
268 * function is used to compare two objects of a given type. The
269 * comparison can be implemented in any way, so long as it returns a
270 * consistent spif_cmp_t value. The simplest way is to compare the
271 * two object variables, as shown below, but often a more sensible
272 * method is warranted.
273 *
274 * @param self The first @c obj instance.
275 * @param other The second @c obj instance.
276 * @return A spif_cmp_t value representing the comparison of @a
277 * self and @a other.
278 *
279 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink, spif_str_comp(), spif_cmp_t, SPIF_CMP_FROM_INT()
280 * @ingroup DOXGRP_OBJ
281 */
282 spif_cmp_t
spif_obj_comp(spif_obj_t self,spif_obj_t other)283 spif_obj_comp(spif_obj_t self, spif_obj_t other)
284 {
285 SPIF_OBJ_COMP_CHECK_NULL(self, other);
286 return SPIF_CMP_FROM_INT(SPIF_CAST(ulong) self - SPIF_CAST(ulong) other);
287 }
288
289 /**
290 * Duplicate an @c obj and its resources.
291 *
292 * The @c dup standard member function is responsible for returning a
293 * new object instance which contains the exact same value as the
294 * instance supplied to it. That means that any values are copied
295 * from the original to the duplicate, and any references (pointers
296 * and objects) are duplicated in the new instance, using MALLOC(),
297 * the member object's @c dup function, etc. The object returned MUST
298 * be independent of the original; i.e., calling @c done or @c del on
299 * the duplicate MUST NOT destroy or affect the original, or any of
300 * its data, in any way.
301 *
302 * @param self The @c obj instance.
303 * @return An exact duplicate of @a self which is identical to,
304 * but programmatically independent of, the original.
305 *
306 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink, spif_str_dup()
307 * @ingroup DOXGRP_OBJ
308 */
309 spif_obj_t
spif_obj_dup(spif_obj_t self)310 spif_obj_dup(spif_obj_t self)
311 {
312 spif_obj_t tmp;
313
314 ASSERT_RVAL(!SPIF_OBJ_ISNULL(self), SPIF_NULL_TYPE(obj));
315 tmp = spif_obj_new();
316 memcpy(tmp, self, SPIF_SIZEOF_TYPE(obj));
317 return tmp;
318 }
319
320 /**
321 * Obtain the class name of an @c obj.
322 *
323 * The @c type standard member function is responsible for returning
324 * the class name (as a spif_classname_t) of the supplied object. You
325 * will almost certainly want to implement it exactly as seen here.
326 * If you don't, know why.
327 *
328 * @param self The @c obj instance.
329 * @return The class name of @a self.
330 *
331 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink
332 * @ingroup DOXGRP_OBJ
333 */
334 spif_classname_t
spif_obj_type(spif_obj_t self)335 spif_obj_type(spif_obj_t self)
336 {
337 ASSERT_RVAL(!SPIF_OBJ_ISNULL(self), SPIF_NULL_TYPE(classname));
338 return SPIF_OBJ_CLASSNAME(self);
339 }
340
341 /**
342 * Return the class of an object.
343 *
344 * This function returns the class (i.e., spif_class_t) of the
345 * supplied @c obj instance. Thanks to the Magic and Mystery of
346 * typecasting, any LibAST object can be passed to this function to
347 * obtain its class information, like so:
348 * <tt>spif_obj_get_class(SPIF_OBJ(foo))</tt> Or, simply use the
349 * SPIF_OBJ_CLASS() macro.
350 *
351 * Keep in mind that this will return the @a entire class. If you
352 * simply want the class name string, use SPIF_OBJ_CLASSNAME()
353 * instead.
354 *
355 * @param self The @c obj instance.
356 * @return The object's class, or NULL if @a self is NULL.
357 *
358 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink
359 * @ingroup DOXGRP_OBJ
360 */
361 spif_class_t
spif_obj_get_class(spif_obj_t self)362 spif_obj_get_class(spif_obj_t self)
363 {
364 ASSERT_RVAL(!SPIF_OBJ_ISNULL(self), SPIF_NULL_TYPE(class));
365 return SPIF_OBJ_CLASS(self);
366 }
367
368 /**
369 * Set an object's class.
370 *
371 * This function sets the class (i.e., spif_class_t) of the supplied
372 * @c obj instance. Thanks to the Magic and Mystery of typecasting,
373 * any LibAST object can be passed to this function to set its class
374 * information, like so: <tt>spif_obj_set_class(SPIF_OBJ(foo),
375 * SPIF_CLASS_VAR(XXX))</tt>, where <tt>XXX</tt> is the actual type of
376 * the object (like @c str or @c regexp). Any call to the @c init
377 * member of a parent class MUST be immediately followed by a call to
378 * this function like the one above. Failure to do so results in
379 * inaccurate class typing information, which kinda defeats the whole
380 * point, ya know?
381 *
382 * @param self The @c obj instance.
383 * @param cls The @c class for the given instance.
384 * @return #TRUE if successful, #FALSE otherwise.
385 *
386 * @see @link DOXGRP_OBJ LibAST Object Infrastructure @endlink
387 * @ingroup DOXGRP_OBJ
388 */
389 spif_bool_t
spif_obj_set_class(spif_obj_t self,spif_class_t cls)390 spif_obj_set_class(spif_obj_t self, spif_class_t cls)
391 {
392 ASSERT_RVAL(!SPIF_OBJ_ISNULL(self), FALSE);
393 self->cls = cls;
394 return TRUE;
395 }
396
397 /*@}*/
398
399
400
401 /**
402 * @defgroup DOXGRP_OBJ LibAST Object Infrastructure
403 *
404 * This group of types, functions, and pre-processor macros implements
405 * a mechanism for defining and utilizing objects in native C.
406 *
407 * C, as you well know, is a procedural language. It has no native
408 * facilities for doing object-oriented programming. And thusly was
409 * born C++ -- native object facilities with much of the same C syntax
410 * we all know and love. But C++ has one very big (and fatal, IMHO)
411 * flaw: it requires a special compiler.
412 *
413 * That in and of itself is not the end of the world, but it does
414 * create a number of issues in terms of portability, standardization,
415 * speed, and efficiency. Since C has been around for so much longer,
416 * most C compilers are very stable and reliable, and their
417 * optimization routines often do almost as good a job as writing raw
418 * assembly code (particularly the vendor compilers). C++ offers none
419 * of these types of advantages, and C++ compiler availability has
420 * historically been sketchy at best.
421 *
422 * There are really 2 possible solutions to this, both accomplishing
423 * the same end result (using the native C compiler to manipulate an
424 * object model and hierarchy) in two similar, but distinct, ways.
425 * Both approaches require the use of some sort of preprocessor.
426 * Option #1 would be to use a dedicated preprocessor, either
427 * something like m4 or a new creation. This option would probably
428 * allow for cleaner, more native-looking syntax, but it has similar
429 * (and potentially worse) portability problems to those of C++.
430 *
431 * For these reasons, I chose option #2: a CPP-based (i.e.,
432 * macro-based) object model. As you might imagine, the syntax and
433 * usage of such a model bears almost no resemblence whatsoever to
434 * that of a native OO language, as it relies heavily on type-casting
435 * and namespace safety measures implemented within the existing C/CPP
436 * structure. However, the resultant code is native C, which means
437 * you can manipulate data using OO techniques like inheritance,
438 * interface classes, etc., without incurring the speed/portability
439 * penalties of using the C++ compiler. Plus, you can build libraries
440 * that can be easily linked to both C and C++ programs.
441 *
442 * If you'd like to see a sample program which demonstrates creation
443 * and management of LibAST objects, please look here:
444 * @link obj_example.c @endlink.
445 */
446
447 /**
448 * @example obj_example.c
449 * Example code for using the LibAST Object Infrastructure
450 *
451 * This is a contrived, but informational, example of using LibAST's
452 * object system. MORE HERE
453 *
454 * Here's the complete source code:
455 */
456