spec.c 19 KB

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