r14052: Remove BASEDIR use in the Makefile. BASEDIR=prefix=@prefix@ till now.
[Samba/gebeck_regimport.git] / source3 / utils / debugparse.c
blobc5fe3e2ee85f20a684dfa974fdc966049691e904
1 /* ========================================================================== **
2 * debugparse.c
4 * Copyright (C) 1998 by Christopher R. Hertel
6 * Email: crh@ubiqx.mn.org
8 * -------------------------------------------------------------------------- **
9 * This module is a very simple parser for Samba debug log files.
10 * -------------------------------------------------------------------------- **
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License along with this library; if not, write to the Free
24 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * -------------------------------------------------------------------------- **
27 * The important function in this module is dbg_char2token(). The rest is
28 * basically fluff. (Potentially useful fluff, but still fluff.)
29 * ========================================================================== **
32 #include "debugparse.h"
34 /* -------------------------------------------------------------------------- **
35 * Constants...
37 * DBG_BSIZE - This internal constant is used only by dbg_test(). It is the
38 * size of the read buffer. I've tested the function using a
39 * DBG_BSIZE value of 2.
42 #define DBG_BSIZE 128
44 /* -------------------------------------------------------------------------- **
45 * Functions...
48 const char *dbg_token2string( dbg_Token tok )
49 /* ------------------------------------------------------------------------ **
50 * Given a token, return a string describing the token.
52 * Input: tok - One of the set of dbg_Tokens defined in debugparse.h.
54 * Output: A string identifying the token. This is useful for debugging,
55 * etc.
57 * Note: If the token is not known, this function will return the
58 * string "<unknown>".
60 * ------------------------------------------------------------------------ **
63 switch( tok )
65 case dbg_null:
66 return( "null" );
67 case dbg_ignore:
68 return( "ignore" );
69 case dbg_header:
70 return( "header" );
71 case dbg_timestamp:
72 return( "time stamp" );
73 case dbg_level:
74 return( "level" );
75 case dbg_sourcefile:
76 return( "source file" );
77 case dbg_function:
78 return( "function" );
79 case dbg_lineno:
80 return( "line number" );
81 case dbg_message:
82 return( "message" );
83 case dbg_eof:
84 return( "[EOF]" );
86 return( "<unknown>" );
87 } /* dbg_token2string */
89 dbg_Token dbg_char2token( dbg_Token *state, int c )
90 /* ------------------------------------------------------------------------ **
91 * Parse input one character at a time.
93 * Input: state - A pointer to a token variable. This is used to
94 * maintain the parser state between calls. For
95 * each input stream, you should set up a separate
96 * state variable and initialize it to dbg_null.
97 * Pass a pointer to it into this function with each
98 * character in the input stream. See dbg_test()
99 * for an example.
100 * c - The "current" character in the input stream.
102 * Output: A token.
103 * The token value will change when delimiters are found,
104 * which indicate a transition between syntactical objects.
105 * Possible return values are:
107 * dbg_null - The input character was an end-of-line.
108 * This resets the parser to its initial state
109 * in preparation for parsing the next line.
110 * dbg_eof - Same as dbg_null, except that the character
111 * was an end-of-file.
112 * dbg_ignore - Returned for whitespace and delimiters.
113 * These lexical tokens are only of interest
114 * to the parser.
115 * dbg_header - Indicates the start of a header line. The
116 * input character was '[' and was the first on
117 * the line.
118 * dbg_timestamp - Indicates that the input character was part
119 * of a header timestamp.
120 * dbg_level - Indicates that the input character was part
121 * of the debug-level value in the header.
122 * dbg_sourcefile - Indicates that the input character was part
123 * of the sourcefile name in the header.
124 * dbg_function - Indicates that the input character was part
125 * of the function name in the header.
126 * dbg_lineno - Indicates that the input character was part
127 * of the DEBUG call line number in the header.
128 * dbg_message - Indicates that the input character was part
129 * of the DEBUG message text.
131 * ------------------------------------------------------------------------ **
134 /* The terminating characters that we see will greatly depend upon
135 * how they are read. For example, if gets() is used instead of
136 * fgets(), then we will not see newline characters. A lot also
137 * depends on the calling function, which may handle terminators
138 * itself.
140 * '\n', '\0', and EOF are all considered line terminators. The
141 * dbg_eof token is sent back if an EOF is encountered.
143 * Warning: only allow the '\0' character to be sent if you are
144 * using gets() to read whole lines (thus replacing '\n'
145 * with '\0'). Sending '\0' at the wrong time will mess
146 * up the parsing.
148 switch( c )
150 case EOF:
151 *state = dbg_null; /* Set state to null (initial state) so */
152 return( dbg_eof ); /* that we can restart with new input. */
153 case '\n':
154 case '\0':
155 *state = dbg_null; /* A newline or eoln resets to the null state. */
156 return( dbg_null );
159 /* When within the body of the message, only a line terminator
160 * can cause a change of state. We've already checked for line
161 * terminators, so if the current state is dbg_msgtxt, simply
162 * return that as our current token.
164 if( dbg_message == *state )
165 return( dbg_message );
167 /* If we are at the start of a new line, and the input character
168 * is an opening bracket, then the line is a header line, otherwise
169 * it's a message body line.
171 if( dbg_null == *state )
173 if( '[' == c )
175 *state = dbg_timestamp;
176 return( dbg_header );
178 *state = dbg_message;
179 return( dbg_message );
182 /* We've taken care of terminators, text blocks and new lines.
183 * The remaining possibilities are all within the header line
184 * itself.
187 /* Within the header line, whitespace can be ignored *except*
188 * within the timestamp.
190 if( isspace( c ) )
192 /* Fudge. The timestamp may contain space characters. */
193 if( (' ' == c) && (dbg_timestamp == *state) )
194 return( dbg_timestamp );
195 /* Otherwise, ignore whitespace. */
196 return( dbg_ignore );
199 /* Okay, at this point we know we're somewhere in the header.
200 * Valid header *states* are: dbg_timestamp, dbg_level,
201 * dbg_sourcefile, dbg_function, and dbg_lineno.
203 switch( c )
205 case ',':
206 if( dbg_timestamp == *state )
208 *state = dbg_level;
209 return( dbg_ignore );
211 break;
212 case ']':
213 if( dbg_level == *state )
215 *state = dbg_sourcefile;
216 return( dbg_ignore );
218 break;
219 case ':':
220 if( dbg_sourcefile == *state )
222 *state = dbg_function;
223 return( dbg_ignore );
225 break;
226 case '(':
227 if( dbg_function == *state )
229 *state = dbg_lineno;
230 return( dbg_ignore );
232 break;
233 case ')':
234 if( dbg_lineno == *state )
236 *state = dbg_null;
237 return( dbg_ignore );
239 break;
242 /* If the previous block did not result in a state change, then
243 * return the current state as the current token.
245 return( *state );
246 } /* dbg_char2token */
248 void dbg_test( void )
249 /* ------------------------------------------------------------------------ **
250 * Simple test function.
252 * Input: none.
253 * Output: none.
254 * Notes: This function was used to test dbg_char2token(). It reads a
255 * Samba log file from stdin and prints parsing info to stdout.
256 * It also serves as a simple example.
258 * ------------------------------------------------------------------------ **
261 char bufr[DBG_BSIZE];
262 int i;
263 int linecount = 1;
264 dbg_Token old = dbg_null,
265 newtok= dbg_null,
266 state = dbg_null;
268 while( fgets( bufr, DBG_BSIZE, stdin ) )
270 for( i = 0; bufr[i]; i++ )
272 old = newtok;
273 newtok = dbg_char2token( &state, bufr[i] );
274 switch( newtok )
276 case dbg_header:
277 if( linecount > 1 )
278 (void)putchar( '\n' );
279 break;
280 case dbg_null:
281 linecount++;
282 break;
283 case dbg_ignore:
284 break;
285 default:
286 if( old != newtok )
287 (void)printf( "\n[%05d]%12s: ", linecount, dbg_token2string(newtok) );
288 (void)putchar( bufr[i] );
292 (void)putchar( '\n' );
293 } /* dbg_test */
296 /* -------------------------------------------------------------------------- **
297 * This simple main line can be uncommented and used to test the parser.
301 * int main( void )
303 * dbg_test();
304 * return( 0 );
308 /* ========================================================================== */