Re: Request for Comment: Callable CRM114 Classifiers (libcrm114) --> OOBC
"Ger Hobbelt" <[email protected]>
| Newsgroups | gmane.mail.spam.crm114 |
|---|---|
| Message-ID | <[email protected]> |
On Sun, Oct 5, 2008 at 11:03 PM, Eugene Crosser <[email protected]> wrote: > Well, as to me, I quite like your quasi-OO approach. Still the macro > stuff in your examples looks a bit too verbose/complicated to me... ?? ;-S That's very basic macro stuff. (Anyway, could do the same with 'inline' functions for modern C compilers if you like; it's just stuffing a 'severity code' into the upper byte of a 4-byte (or bigger) int and storing the section number in the lower 24 bits (3 bytes). layout of my 'level' int is thus: MSB (byte 3..): severity (>= 8 bits) LSB (byte 0..2): facility (24 bits) The macros allow me to define the severity and facility numbers in #define's or enums, whichever I like more, without the need to remember their bit positions. Something like this if your favorite flavor is 'enum' instead of '#define': enum severity { crm_s_success = 0, crm_s_developer, // I don't really like 'internal' and 'user' levels, but think of this as 'internal_trace' crm_s_informational, // ~ 'user' crm_s_warning, crm_s_error, crm_s_fatal }; and similar for the facility codes. Note that you could use the same scheme for both trace level and error codes from libcrm114 when we move the 'facility ID' up in there to allow room for individual error or sequence ids a la VMS/NT. The macros I showed before will mix them into that 32+ bit int called 'level' and off you go. The idea is extremely old; two current operating system series that exhibit this sort of behaviour (= method of encoding) for all their error codes are VMS (and naturally: OpenVMS) and Windows NT (3.x, 4, 2000, 2003, 2005, 2008) and all Windows 2000, Windows XP and Vista's out there. (That because some of the VMS designers ended up in the Microsoft team.) Incidentially, OpenSSL has a similar scheme for error codes; this stuff is not limited to 'systems programming'. You should quickly scan this document to get the idea here (Have a gander at figure 3-5). All I'm doing is not only using this trick for error codes but also for my debug/trace codes, which, if you look at it the right way, are VERY similar to 'warnings', 'informationals' and 'success' codes. Furthermore, I simplified it down to just severity and facility; the full version has severity, facility, error code (would be an additional message sequence ID then in our 'tracing/diagnostics logging' case) and a few extra flags. Easy text, with pictures: ;-) http://h71000.www7.hp.com/commercial/c/docs/5492profile_016.html > > And, I'd rather not expose the CTX structure to the user of the API, as > in your examples. Instead of > > this->trace_callback(this, ...) > > the user could write > > crm114_trace(this, ...) WHOA!!! I have to correct that mental image! The *only ones* coding stuff like > this->trace_callback(this, ...) are the libcrm114 dev's themselves: *that* is how it looks on the *inside*. And for them, it's easy as can be: one idiom, no exceptions, for everything that diag (or error, if we adopt the same interface there, without the error stack). *Users* of libcrm114, however, just write that single callback like I showed before and they're _done_. Callbacks call *from* libcrm114 to the 'outside'. Given that the target audience for libcrm114 are *developers* I assume a minimum level of professionalism there: a callback shouldn't be overtaxing them. And if it is, well, suffice to say I'd rather NOT use their software. (Yep, I've met the sort. Boy, are they fast. Wham! Bam! Thank you, m'am! And they're gone, mom is going to have a litter Hiroshima style, and folks like me get invited to do version 2, because cleaning would mean there'd be nothing left under the layer of dung.) The actual CRM114 *USERS* don't get bothered by libcrm114 anyway, because anyone who's interested in doing the spamfiltering and all like they used to, just keep on using the major application using libcrm114: that'd be '/usr/bin/crm114' like before. > (presuming 'this' is the 'context' type.) The function itself could be like > > void crm114_trace (crm114_ctx_t this, ...) { > if (this->trace_callback) { > this->trace_callback(this, ...) > } else { > fprintf(stderr, ....); > } > } As that's for *internal* use only, you can write a function there if you don't want that 'this->' everywhere (I'd do it using either inline functions or macros as function call overhead is adding more trouble to varargs than the function is worth. See for a howto the fatalerror_ex() et al macros in the GerH distro. > this way you will have more freedom to play with the structure without > the user noticing. And, it looks more concise and possibly less scary > ;-) [Also, the cost of initial implementation may be lower.] Same cost, really: global find&replace internal log lines to trace callbacks; user has to write one simple function anyway.Since I don't have that extra 'if' of yours in there, I might say mine's even easier. ;-) If the internal find&replace would be mindboggling for Bill, I can do that on a rainy morning (takes three rounds, 's all), no sweat. Wouldn't even have to write an awk script for that; just a few keyboard recording macros in one of my favorite editors, and we're done. > >> typedef void crm_trace_callback_t(crm_config_t *obj, int level, const >> char *fmt_msg, ...); >> ---------------------------- >> (which, incidentally, you can augment in GCC (without hurting >> portability to other compilers) to tell GCC he should check this >> callback interface as if it were a regular printf() style formatted >> vararg, so you'd get nice warnings when screwing up your %d, %s, etc. >> elements) > > Wow, I did not know that! How'd you do that? he he. copy&paste from the GerH crm114 macros (crm114.h): void untrappableerror_std(int lineno, const char *srcfile, const char *funcname, const char *msg1, const char *msg2) __attribute__((__noreturn__)); void untrappableerror_ex(int lineno, const char *srcfile, const char *funcname, const char *msg, ...) __attribute__((__noreturn__, __format__(__printf__, 4, 5))); void untrappableerror_va(int lineno, const char *srcfile, const char *funcname, const char *msg, va_list args) __attribute__((__noreturn__, __format__(__printf__, 4, 0))); I'll assume you can 'read' the above intuitively. If not, see the gcc manuals for more niftyness. Note: ZERO run-time overhead: this is adding attributes to symbols in the compiler AST only. Any compiler who doesn't sport __attribute__() can simple do: #define __attribute__(arg) /* black hole */ and you're set. Bonus: the above can be driven from a ./configure script, so you can schlepp your code around to non-gcc platforms as well, no worries. -- Met vriendelijke groeten / Best regards, Ger Hobbelt -------------------------------------------------- web: http://www.hobbelt.com/ http://www.hebbut.net/ mail: [email protected] mobile: +31-6-11 120 978 -------------------------------------------------- ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/