My Project
 All Classes Files Functions Variables Enumerations Enumerator Friends Macros Pages
lprintf.h
1 #ifndef lprintf_h
2 #define lprintf_h
3 
4 #include "gcp/util/common/Logger.h"
5 
6 #include <stdio.h>
7 #include <stdarg.h>
8 
9 /*
10  * lprintf() is a drop-in replacement to fprintf() and printf()
11  * designed for redirecting stdout and/or stderr messages to alternate
12  * logging channels such as message queues, TCP/IP streams, widgets
13  * etc.. Note that lprintf(stream,...) will behave identically to
14  * fprintf(stream,...) until divert_lprintf(stream,...) is called to
15  * register a logging function to that stream.
16  *
17  * A limitation of this facility is that when logging to a function is
18  * enabled, individual messages are truncated at LOG_MSGLEN bytes
19  * (actually LOG_MSGLEN+1 when account is take of the trailing '\0').
20  *
21  * Note that the combination of lprintf() and print_format() [and
22  * presumably its vxWorks equivalent, fioFormatV()] use about 750
23  * bytes of stack space.
24  *
25  * Threads issues:
26  * In pthreads programs be sure to define the _POSIX_C_SOURCE macro
27  * to be at least 199506L during compilation of all files that include
28  * lprintf.h (including lprintf.c).
29  *
30  * In VxWorks programs define VXW when compiling any file that includes
31  * lprintf.h, and call vw_install_lprintf() before creating the first task
32  * [apart from the caller of vw_install_lprintf()] that will use lprintf().
33  * If subsequently you need to deinstall the module that contains lprintf(),
34  * make sure that all tasks that use lprintf() have been deleted (with the
35  * possible exception of the task that calls vw_remove_lprintf()), then
36  * call vw_remove_lprintf() to remove the task creation and deletion
37  * hooks that were installed by vw_install_lprintf().
38  *
39  * Provided that the above guidlines are followed, divert_lprintf()
40  * and lprintf() will operate on a per thread basis. In particular,
41  * when logging functions are registered to a thread, the associated
42  * streams will be line buffered on a per thread basis to prevent
43  * interleaving of partial lines from different threads.
44  */
45 
46 /*
47  * VxWorks installation and removal functions for lprintf().
48  * See the above discussion of "Threads issues".
49  */
50 #ifdef VXW
51 int vw_install_lprintf(void);
52 int vw_remove_lprintf(void);
53 #endif
54 
55 /*
56  * The following is the length of the longest log message
57  * (excluding '\0'). Longer messages will be truncated before
58  * being dispatched to the function registered to the associated
59  * stream.
60  */
61 #define LOG_MSGLEN 127
62 
63 /*
64  * When this header is compiled with gcc, the following macro
65  * is expanded at the end of the prototype of lprintf. The
66  * result informs gcc that the format and trailing arguments should
67  * be checked as though the function were printf().
68  */
69 #undef CHECK_FORMAT
70 #ifdef __GNUC__
71 #define CHECK_FORMAT __attribute__ ((format (printf, 2, 3)))
72 #else
73 #define CHECK_FORMAT
74 #endif
75 
76 /*
77  * The following functions are drop-in logging replacements for the
78  * similarly named stdio functions. When logging is disabled, they
79  * behave identically to their stdio counterparts.
80  */
81 int lprintf(FILE *stream, const char *fmt, ...) CHECK_FORMAT;
82 #undef CHECK_FORMAT
83 
84 int vlprintf(FILE *stream, const char *fmt, va_list ap);
85 int lputc(int c, FILE *stream);
86 int lputs(const char *s, FILE *stream);
87 int lflush(FILE *stream);
88 
89 /*
90  * The dispatch function is passed an enumerated equivalent of
91  * stdout or stderr, depending upon which stream the caller
92  * presented to lprintf(). This is useful if a single
93  * dispatch function is registered to both stdout and stderr.
94  */
95 namespace gcp {
96  namespace control {
97 
98  enum LogStream {
99  LOG_STDOUT, /* Log to stdout */
100  LOG_STDERR /* Log to stderr */
101  };
102 
103  };
104 }
105 
106 /*
107  * Application-specific dispatch functions and their prototypes
108  * should be declared using the following macro. The arguments
109  * of a dispatch function are used as follows:
110  *
111  * Input:
112  * message char * The latest message composed by lprintf().
113  * This will be at most LOG_MSGLEN+1 bytes in
114  * length and will '\0' terminated, regardless
115  * of whether the message had to be truncated.
116  * Note that the trailing newline is omitted.
117  * id LogStream The identity of the stream that the caller
118  * of lprintf() cited. This is only useful if
119  * the same dispatch function has been assigned
120  * to stdout and stderr.
121  * context void * The value of the 'context' argument of
122  * divert_lprintf() when the dispatch function
123  * was registered. Note that in a threaded
124  * environment, modifications to this context
125  * will need to be semaphore protected.
126  * Output:
127  * return int 0 - The message was logged without error.
128  * 1 - An error occured. This tells lprintf()
129  * to return -1 instead of a character count.
130  */
131 #define LOG_DISPATCHER(fn) int (fn)(char *message, gcp::control::LogStream id, void *context)
132 
133 /*
134  * The following function registers a function to be called to process
135  * the lprintf() line-buffered output of stdout and stderr. To revert
136  * the specified stream to fprintf(), send log_fn=0. In order to allow
137  * nesting of calls to divert_lprintf(), if the old_fn and old_context
138  * arguments are both non-NULL, then any previous dispatch function
139  * and its context will be assigned to them. The caller can then
140  * reinstall them if needed.
141  */
142 int divert_lprintf(FILE *stream, LOG_DISPATCHER(*log_fn), void *context,
143  LOG_DISPATCHER(**old_fn), void **old_context);
144 
145 #endif