1 /*
2 * This file is part of the zlog Library.
3 *
4 * Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
5 *
6 * Licensed under the LGPL v2.1, see the file COPYING in base directory.
7 */
8
9 #include "fmacros.h"
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <sys/time.h>
16 #include <time.h>
17 #include <errno.h>
18 #include <sys/types.h>
19 #include <unistd.h>
20
21 #include "conf.h"
22 #include "spec.h"
23 #include "level_list.h"
24 #include "zc_defs.h"
25
26
27 #define ZLOG_DEFAULT_TIME_FMT "%F %T"
28 #define ZLOG_HEX_HEAD \
29 "\n 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF"
30
31 /*******************************************************************************/
zlog_spec_profile(zlog_spec_t * a_spec,int flag)32 void zlog_spec_profile(zlog_spec_t * a_spec, int flag)
33 {
34 zc_assert(a_spec,);
35 zc_profile(flag, "----spec[%p][%.*s][%s|%d][%s,%ld,%ld][%s]----",
36 a_spec,
37 a_spec->len, a_spec->str,
38 a_spec->time_fmt,
39 a_spec->time_cache_index,
40 a_spec->print_fmt, (long)a_spec->max_width, (long)a_spec->min_width,
41 a_spec->mdc_key);
42 return;
43 }
44
45 /*******************************************************************************/
46 /* implementation of write function */
47
zlog_spec_write_time(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)48 static int zlog_spec_write_time(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
49 {
50 zlog_time_cache_t * a_cache = a_thread->event->time_caches + a_spec->time_cache_index;
51 time_t now_sec = a_thread->event->time_stamp.tv_sec;
52 struct tm *time_local = &(a_thread->event->time_local);
53
54 /* the event meet the 1st time_spec in his life cycle */
55 if (!now_sec) {
56 gettimeofday(&(a_thread->event->time_stamp), NULL);
57 now_sec = a_thread->event->time_stamp.tv_sec;
58 }
59
60 /* When this event's last cached time_local is not now */
61 if (a_thread->event->time_local_sec != now_sec) {
62 localtime_r(&(now_sec), time_local);
63 a_thread->event->time_local_sec = now_sec;
64 }
65
66 /* When this spec's last cache time string is not now */
67 if (a_cache->sec != now_sec) {
68 a_cache->len = strftime(a_cache->str, sizeof(a_cache->str), a_spec->time_fmt, time_local);
69 a_cache->sec = now_sec;
70 }
71
72 return zlog_buf_append(a_buf, a_cache->str, a_cache->len);
73 }
74
75 #if 0
76 static int zlog_spec_write_time_D(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
77 {
78 if (!a_thread->event->time_stamp.tv_sec) {
79 gettimeofday(&(a_thread->event->time_stamp), NULL);
80 }
81
82 /*
83 * It is modified when time slips one second.
84 * So it is a strong cache, as Default time format is always %F %T.
85 * That's why I said %D is faster than %d()
86 */
87 if (a_thread->event->time_stamp.tv_sec != a_thread->event->time_last_D) {
88
89 a_thread->event->time_last_D = a_thread->event->time_stamp.tv_sec;
90 localtime_r(&(a_thread->event->time_stamp.tv_sec),
91 &(a_thread->event->time_local));
92
93 strftime(a_thread->event->time_cache_D,
94 sizeof(a_thread->event->time_cache_D),
95 ZLOG_DEFAULT_TIME_FMT, &(a_thread->event->time_local) );
96 }
97 return zlog_buf_append(a_buf, a_thread->event->time_cache_D, sizeof(a_thread->event->time_cache_D) - 1);
98 }
99 #endif
100
zlog_spec_write_ms(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)101 static int zlog_spec_write_ms(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
102 {
103 if (!a_thread->event->time_stamp.tv_sec) {
104 gettimeofday(&(a_thread->event->time_stamp), NULL);
105 }
106 return zlog_buf_printf_dec32(a_buf, (a_thread->event->time_stamp.tv_usec / 1000), 3);
107 }
108
zlog_spec_write_us(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)109 static int zlog_spec_write_us(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
110 {
111 if (!a_thread->event->time_stamp.tv_sec) {
112 gettimeofday(&(a_thread->event->time_stamp), NULL);
113 }
114 return zlog_buf_printf_dec32(a_buf, a_thread->event->time_stamp.tv_usec, 6);
115 }
116
zlog_spec_write_mdc(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)117 static int zlog_spec_write_mdc(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
118 {
119 zlog_mdc_kv_t *a_mdc_kv;
120
121 a_mdc_kv = zlog_mdc_get_kv(a_thread->mdc, a_spec->mdc_key);
122 if (!a_mdc_kv) {
123 zc_error("zlog_mdc_get_kv key[%s] fail", a_spec->mdc_key);
124 return 0;
125 }
126
127 return zlog_buf_append(a_buf, a_mdc_kv->value, a_mdc_kv->value_len);
128 }
129
zlog_spec_write_str(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)130 static int zlog_spec_write_str(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
131 {
132 return zlog_buf_append(a_buf, a_spec->str, a_spec->len);
133 }
134
zlog_spec_write_category(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)135 static int zlog_spec_write_category(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
136 {
137 return zlog_buf_append(a_buf, a_thread->event->category_name, a_thread->event->category_name_len);
138 }
139
zlog_spec_write_srcfile(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)140 static int zlog_spec_write_srcfile(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
141 {
142 if (!a_thread->event->file) {
143 return zlog_buf_append(a_buf, "(file=null)", sizeof("(file=null)") - 1);
144 } else {
145 return zlog_buf_append(a_buf, a_thread->event->file, a_thread->event->file_len);
146 }
147 }
148
zlog_spec_write_srcfile_neat(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)149 static int zlog_spec_write_srcfile_neat(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
150 {
151 char *p;
152
153 if ((p = strrchr(a_thread->event->file, '/')) != NULL) {
154 return zlog_buf_append(a_buf, p + 1,
155 (char*)a_thread->event->file + a_thread->event->file_len - p - 1);
156 } else {
157 if (!a_thread->event->file) {
158 return zlog_buf_append(a_buf, "(file=null)", sizeof("(file=null)") - 1);
159 } else {
160 return zlog_buf_append(a_buf, a_thread->event->file, a_thread->event->file_len);
161 }
162 }
163 }
164
zlog_spec_write_srcline(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)165 static int zlog_spec_write_srcline(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
166 {
167
168 return zlog_buf_printf_dec64(a_buf, a_thread->event->line, 0);
169 }
170
zlog_spec_write_srcfunc(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)171 static int zlog_spec_write_srcfunc(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
172 {
173 if (!a_thread->event->file) {
174 return zlog_buf_append(a_buf, "(func=null)", sizeof("(func=null)") - 1);
175 } else {
176 return zlog_buf_append(a_buf, a_thread->event->func, a_thread->event->func_len);
177 }
178 }
179
180
zlog_spec_write_hostname(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)181 static int zlog_spec_write_hostname(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
182 {
183 return zlog_buf_append(a_buf, a_thread->event->host_name, a_thread->event->host_name_len);
184 }
185
zlog_spec_write_newline(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)186 static int zlog_spec_write_newline(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
187 {
188 return zlog_buf_append(a_buf, FILE_NEWLINE, FILE_NEWLINE_LEN);
189 }
190
zlog_spec_write_percent(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)191 static int zlog_spec_write_percent(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
192 {
193 return zlog_buf_append(a_buf, "%", 1);
194 }
195
zlog_spec_write_pid(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)196 static int zlog_spec_write_pid(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
197 {
198 /* 1st in event lifecycle */
199 if (!a_thread->event->pid) {
200 a_thread->event->pid = getpid();
201
202 /* compare with previous event */
203 if (a_thread->event->pid != a_thread->event->last_pid) {
204 a_thread->event->last_pid = a_thread->event->pid;
205 a_thread->event->pid_str_len
206 = sprintf(a_thread->event->pid_str, "%u", a_thread->event->pid);
207 }
208 }
209
210 return zlog_buf_append(a_buf, a_thread->event->pid_str, a_thread->event->pid_str_len);
211 }
212
zlog_spec_write_tid_hex(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)213 static int zlog_spec_write_tid_hex(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
214 {
215
216 /* don't need to get tid again, as tmap_new_thread fetch it already */
217 /* and fork not change tid */
218 return zlog_buf_append(a_buf, a_thread->event->tid_hex_str, a_thread->event->tid_hex_str_len);
219 }
220
zlog_spec_write_tid_long(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)221 static int zlog_spec_write_tid_long(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
222 {
223
224 /* don't need to get tid again, as tmap_new_thread fetch it already */
225 /* and fork not change tid */
226 return zlog_buf_append(a_buf, a_thread->event->tid_str, a_thread->event->tid_str_len);
227 }
228
zlog_spec_write_level_lowercase(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)229 static int zlog_spec_write_level_lowercase(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
230 {
231 zlog_level_t *a_level;
232
233 a_level = zlog_level_list_get(zlog_env_conf->levels, a_thread->event->level);
234 return zlog_buf_append(a_buf, a_level->str_lowercase, a_level->str_len);
235 }
236
zlog_spec_write_level_uppercase(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)237 static int zlog_spec_write_level_uppercase(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
238 {
239 zlog_level_t *a_level;
240
241 a_level = zlog_level_list_get(zlog_env_conf->levels, a_thread->event->level);
242 return zlog_buf_append(a_buf, a_level->str_uppercase, a_level->str_len);
243 }
244
zlog_spec_write_usrmsg(zlog_spec_t * a_spec,zlog_thread_t * a_thread,zlog_buf_t * a_buf)245 static int zlog_spec_write_usrmsg(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
246 {
247 if (a_thread->event->generate_cmd == ZLOG_FMT) {
248 if (a_thread->event->str_format) {
249 return zlog_buf_vprintf(a_buf,
250 a_thread->event->str_format,
251 a_thread->event->str_args);
252 } else {
253 return zlog_buf_append(a_buf, "format=(null)", sizeof("format=(null)")-1);
254 }
255 } else if (a_thread->event->generate_cmd == ZLOG_HEX) {
256 int rc;
257 long line_offset;
258 long byte_offset;
259
260 /* thread buf start == null or len <= 0 */
261 if (a_thread->event->hex_buf == NULL) {
262 rc = zlog_buf_append(a_buf, "buf=(null)", sizeof("buf=(null)")-1);
263 goto zlog_hex_exit;
264 }
265
266 rc = zlog_buf_append(a_buf, ZLOG_HEX_HEAD, sizeof(ZLOG_HEX_HEAD)-1);
267 if (rc) {
268 goto zlog_hex_exit;
269 }
270
271 line_offset = 0;
272 byte_offset = 0;
273
274 while (1) {
275 unsigned char c;
276
277 rc = zlog_buf_append(a_buf, "\n", 1);
278 if (rc) goto zlog_hex_exit;
279
280 rc = zlog_buf_printf_dec64(a_buf, line_offset + 1, 10);
281 if (rc) goto zlog_hex_exit;
282 rc = zlog_buf_append(a_buf, " ", 3);
283 if (rc) goto zlog_hex_exit;
284
285 for (byte_offset = 0; byte_offset < 16; byte_offset++) {
286 if (line_offset * 16 + byte_offset < a_thread->event->hex_buf_len) {
287 c = *((unsigned char *)a_thread->event->hex_buf
288 + line_offset * 16 + byte_offset);
289 rc = zlog_buf_printf_hex(a_buf, c, 2);
290 if (rc) goto zlog_hex_exit;
291 rc = zlog_buf_append(a_buf, " ", 1);
292 if (rc) goto zlog_hex_exit;
293 } else {
294 rc = zlog_buf_append(a_buf, " ", 3);
295 if (rc) goto zlog_hex_exit;
296 }
297 }
298
299 rc = zlog_buf_append(a_buf, " ", 2);
300 if (rc) goto zlog_hex_exit;
301
302 for (byte_offset = 0; byte_offset < 16; byte_offset++) {
303 if (line_offset * 16 + byte_offset < a_thread->event->hex_buf_len) {
304 c = *((unsigned char *)a_thread->event->hex_buf
305 + line_offset * 16 + byte_offset);
306 if (c >= 32 && c <= 126) {
307 rc = zlog_buf_append(a_buf,(char*)&c, 1);
308 if (rc) goto zlog_hex_exit;
309 } else {
310 rc = zlog_buf_append(a_buf, ".", 1);
311 if (rc) goto zlog_hex_exit;
312 }
313 } else {
314 rc = zlog_buf_append(a_buf, " ", 1);
315 if (rc) goto zlog_hex_exit;
316 }
317 }
318
319 if (line_offset * 16 + byte_offset >= a_thread->event->hex_buf_len) {
320 break;
321 }
322
323 line_offset++;
324 }
325
326 zlog_hex_exit:
327 if (rc < 0) {
328 zc_error("write hex msg fail");
329 return -1;
330 } else if (rc > 0) {
331 zc_error("write hex msg, buf is full");
332 return 1;
333 }
334
335 return 0;
336 }
337
338 return 0;
339 }
340
341 /*******************************************************************************/
342 /* implementation of gen function */
343
zlog_spec_gen_msg_direct(zlog_spec_t * a_spec,zlog_thread_t * a_thread)344 static int zlog_spec_gen_msg_direct(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
345 {
346 /* no need to reprint %1.2d here */
347 return a_spec->write_buf(a_spec, a_thread, a_thread->msg_buf);
348 }
349
zlog_spec_gen_msg_reformat(zlog_spec_t * a_spec,zlog_thread_t * a_thread)350 static int zlog_spec_gen_msg_reformat(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
351 {
352 int rc;
353
354 zlog_buf_restart(a_thread->pre_msg_buf);
355
356 rc = a_spec->write_buf(a_spec, a_thread, a_thread->pre_msg_buf);
357 if (rc < 0) {
358 zc_error("a_spec->gen_buf fail");
359 return -1;
360 } else if (rc > 0) {
361 /* buf is full, try printf */
362 }
363
364 return zlog_buf_adjust_append(a_thread->msg_buf,
365 zlog_buf_str(a_thread->pre_msg_buf), zlog_buf_len(a_thread->pre_msg_buf),
366 a_spec->left_adjust, a_spec->min_width, a_spec->max_width);
367 }
368
369 /*******************************************************************************/
zlog_spec_gen_path_direct(zlog_spec_t * a_spec,zlog_thread_t * a_thread)370 static int zlog_spec_gen_path_direct(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
371 {
372 /* no need to reprint %1.2d here */
373 return a_spec->write_buf(a_spec, a_thread, a_thread->path_buf);
374 }
375
zlog_spec_gen_path_reformat(zlog_spec_t * a_spec,zlog_thread_t * a_thread)376 static int zlog_spec_gen_path_reformat(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
377 {
378 int rc;
379
380 zlog_buf_restart(a_thread->pre_path_buf);
381
382 rc = a_spec->write_buf(a_spec, a_thread, a_thread->pre_path_buf);
383 if (rc < 0) {
384 zc_error("a_spec->gen_buf fail");
385 return -1;
386 } else if (rc > 0) {
387 /* buf is full, try printf */
388 }
389
390 return zlog_buf_adjust_append(a_thread->path_buf,
391 zlog_buf_str(a_thread->pre_path_buf), zlog_buf_len(a_thread->pre_path_buf),
392 a_spec->left_adjust, a_spec->min_width, a_spec->max_width);
393 }
394
395 /*******************************************************************************/
zlog_spec_gen_archive_path_direct(zlog_spec_t * a_spec,zlog_thread_t * a_thread)396 static int zlog_spec_gen_archive_path_direct(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
397 {
398 /* no need to reprint %1.2d here */
399 return a_spec->write_buf(a_spec, a_thread, a_thread->archive_path_buf);
400 }
401
zlog_spec_gen_archive_path_reformat(zlog_spec_t * a_spec,zlog_thread_t * a_thread)402 static int zlog_spec_gen_archive_path_reformat(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
403 {
404 int rc;
405
406 zlog_buf_restart(a_thread->pre_path_buf);
407
408 rc = a_spec->write_buf(a_spec, a_thread, a_thread->pre_path_buf);
409 if (rc < 0) {
410 zc_error("a_spec->gen_buf fail");
411 return -1;
412 } else if (rc > 0) {
413 /* buf is full, try printf */
414 }
415
416 return zlog_buf_adjust_append(a_thread->archive_path_buf,
417 zlog_buf_str(a_thread->pre_path_buf), zlog_buf_len(a_thread->pre_path_buf),
418 a_spec->left_adjust, a_spec->min_width, a_spec->max_width);
419 }
420
421 /*******************************************************************************/
zlog_spec_parse_print_fmt(zlog_spec_t * a_spec)422 static int zlog_spec_parse_print_fmt(zlog_spec_t * a_spec)
423 {
424 /* -12.35 12 .35 */
425 char *p, *q;
426 long i, j;
427
428 p = a_spec->print_fmt;
429 if (*p == '-') {
430 a_spec->left_adjust = 1;
431 p++;
432 } else {
433 a_spec->left_adjust = 0;
434 }
435
436 i = j = 0;
437 sscanf(p, "%ld.", &i);
438 q = strchr(p, '.');
439 if (q) sscanf(q, ".%ld", &j);
440
441 a_spec->min_width = (size_t) i;
442 a_spec->max_width = (size_t) j;
443 return 0;
444 }
445
446 /*******************************************************************************/
zlog_spec_del(zlog_spec_t * a_spec)447 void zlog_spec_del(zlog_spec_t * a_spec)
448 {
449 zc_assert(a_spec,);
450 free(a_spec);
451 zc_debug("zlog_spec_del[%p]", a_spec);
452 }
453
454 /* a spec may consist of
455 * a const string: /home/bb
456 * a string begin with %: %12.35d(%F %X,%l)
457 */
zlog_spec_new(char * pattern_start,char ** pattern_next,int * time_cache_count)458 zlog_spec_t *zlog_spec_new(char *pattern_start, char **pattern_next, int *time_cache_count)
459 {
460 char *p;
461 int nscan = 0;
462 int nread = 0;
463 zlog_spec_t *a_spec;
464
465 zc_assert(pattern_start, NULL);
466 zc_assert(pattern_next, NULL);
467
468 a_spec = calloc(1, sizeof(zlog_spec_t));
469 if (!a_spec) {
470 zc_error("calloc fail, errno[%d]", errno);
471 return NULL;
472 }
473
474 a_spec->str = p = pattern_start;
475
476 switch (*p) {
477 case '%':
478 /* a string begin with %: %12.35d(%F %X) */
479
480 /* process width and precision char in %-12.35P */
481 nread = 0;
482 nscan = sscanf(p, "%%%[.0-9-]%n", a_spec->print_fmt, &nread);
483 if (nscan == 1) {
484 a_spec->gen_msg = zlog_spec_gen_msg_reformat;
485 a_spec->gen_path = zlog_spec_gen_path_reformat;
486 a_spec->gen_archive_path = zlog_spec_gen_archive_path_reformat;
487 if (zlog_spec_parse_print_fmt(a_spec)) {
488 zc_error("zlog_spec_parse_print_fmt fail");
489 goto err;
490 }
491 } else {
492 nread = 1; /* skip the % char */
493 a_spec->gen_msg = zlog_spec_gen_msg_direct;
494 a_spec->gen_path = zlog_spec_gen_path_direct;
495 a_spec->gen_archive_path = zlog_spec_gen_archive_path_direct;
496 }
497
498 p += nread;
499
500 if (*p == 'd') {
501 if (*(p+1) != '(') {
502 /* without '(' , use default */
503 strcpy(a_spec->time_fmt, ZLOG_DEFAULT_TIME_FMT);
504 p++;
505 } else if (STRNCMP(p, ==, "d()", 3)) {
506 /* with () but without detail time format,
507 * keep a_spec->time_fmt=="" */
508 strcpy(a_spec->time_fmt, ZLOG_DEFAULT_TIME_FMT);
509 p += 3;
510 } else {
511 nread = 0;
512 nscan = sscanf(p, "d(%[^)])%n", a_spec->time_fmt, &nread);
513 if (nscan != 1) {
514 nread = 0;
515 }
516 p += nread;
517 if (*(p - 1) != ')') {
518 zc_error("in string[%s] can't find match \')\'", a_spec->str);
519 goto err;
520 }
521 }
522
523 a_spec->time_cache_index = *time_cache_count;
524 (*time_cache_count)++;
525 a_spec->write_buf = zlog_spec_write_time;
526
527 *pattern_next = p;
528 a_spec->len = p - a_spec->str;
529 break;
530 }
531
532 if (*p == 'M') {
533 nread = 0;
534 nscan = sscanf(p, "M(%[^)])%n", a_spec->mdc_key, &nread);
535 if (nscan != 1) {
536 nread = 0;
537 if (STRNCMP(p, ==, "M()", 3)) {
538 nread = 3;
539 }
540 }
541 p += nread;
542 if (*(p - 1) != ')') {
543 zc_error("in string[%s] can't find match \')\'", a_spec->str);
544 goto err;
545 }
546
547 *pattern_next = p;
548 a_spec->len = p - a_spec->str;
549 a_spec->write_buf = zlog_spec_write_mdc;
550 break;
551 }
552
553 if (STRNCMP(p, ==, "ms", 2)) {
554 p += 2;
555 *pattern_next = p;
556 a_spec->len = p - a_spec->str;
557 a_spec->write_buf = zlog_spec_write_ms;
558 break;
559 } else if (STRNCMP(p, ==, "us", 2)) {
560 p += 2;
561 *pattern_next = p;
562 a_spec->len = p - a_spec->str;
563 a_spec->write_buf = zlog_spec_write_us;
564 break;
565 }
566
567 *pattern_next = p + 1;
568 a_spec->len = p - a_spec->str + 1;
569
570 switch (*p) {
571 case 'c':
572 a_spec->write_buf = zlog_spec_write_category;
573 break;
574 case 'D':
575 strcpy(a_spec->time_fmt, ZLOG_DEFAULT_TIME_FMT);
576 a_spec->time_cache_index = *time_cache_count;
577 (*time_cache_count)++;
578 a_spec->write_buf = zlog_spec_write_time;
579 break;
580 case 'F':
581 a_spec->write_buf = zlog_spec_write_srcfile;
582 break;
583 case 'f':
584 a_spec->write_buf = zlog_spec_write_srcfile_neat;
585 break;
586 case 'H':
587 a_spec->write_buf = zlog_spec_write_hostname;
588 break;
589 case 'L':
590 a_spec->write_buf = zlog_spec_write_srcline;
591 break;
592 case 'm':
593 a_spec->write_buf = zlog_spec_write_usrmsg;
594 break;
595 case 'n':
596 a_spec->write_buf = zlog_spec_write_newline;
597 break;
598 case 'p':
599 a_spec->write_buf = zlog_spec_write_pid;
600 break;
601 case 'U':
602 a_spec->write_buf = zlog_spec_write_srcfunc;
603 break;
604 case 'v':
605 a_spec->write_buf = zlog_spec_write_level_lowercase;
606 break;
607 case 'V':
608 a_spec->write_buf = zlog_spec_write_level_uppercase;
609 break;
610 case 't':
611 a_spec->write_buf = zlog_spec_write_tid_hex;
612 break;
613 case 'T':
614 a_spec->write_buf = zlog_spec_write_tid_long;
615 break;
616 case '%':
617 a_spec->write_buf = zlog_spec_write_percent;
618 break;
619 default:
620 zc_error("str[%s] in wrong format, p[%c]", a_spec->str, *p);
621 goto err;
622 }
623 break;
624 default:
625 /* a const string: /home/bb */
626 *pattern_next = strchr(p, '%');
627 if (*pattern_next) {
628 a_spec->len = *pattern_next - p;
629 } else {
630 a_spec->len = strlen(p);
631 *pattern_next = p + a_spec->len;
632 }
633 a_spec->write_buf = zlog_spec_write_str;
634 a_spec->gen_msg = zlog_spec_gen_msg_direct;
635 a_spec->gen_path = zlog_spec_gen_path_direct;
636 a_spec->gen_archive_path = zlog_spec_gen_archive_path_direct;
637 }
638
639 zlog_spec_profile(a_spec, ZC_DEBUG);
640 return a_spec;
641 err:
642 zlog_spec_del(a_spec);
643 return NULL;
644 }
645
646