add debug
[kps.git] / output.h
blobcd3d1c50d8324da79bcf95742fba7650d339563b
1 #ifndef INC_OUTPUT
2 #define INC_OUTPUT
4 #include "patch_sta.h"
6 int total_num;
7 int node_cnt;
9 #define __TOTAL_AVERAGE_PATCH(head, type, member, cat, fp) do {\
10 type *cur; \
11 node_cnt = 0; \
12 total_num = 0; \
13 list_for_each_entry(cur, head, member) { \
14 node_cnt++; \
15 if (g_line == SELECT) \
16 total_num = total_num + cur->chgline;\
17 else \
18 total_num = total_num + cur->cnt; \
19 } \
20 if (fp) { \
21 fprintf(fp, "Total %s of this kernel release: %u\n",\
22 statistics_msg, total_num);\
23 fprintf(fp, "%d %s contribute their works to this kernel release.\n",\
24 node_cnt, cat);\
25 fprintf(fp, "Averagely, every %s committed %u %s.\n\n", \
26 cat, total_num?total_num/node_cnt:0, statistics_msg); \
27 } else { \
28 printf("Total %s of this kernel release: %u\n", \
29 statistics_msg, total_num); \
30 printf("%d %s contribute their works to this kernel release.\n",\
31 node_cnt, cat);\
32 printf("Averagely, every %s committed %u %s.\n\n", \
33 cat, total_num?total_num/node_cnt:0, statistics_msg); \
34 } \
35 } while (0)
37 #define TOTAL_AVERAGE_PATCH(head, type, member, cat) \
38 __TOTAL_AVERAGE_PATCH(head, type, member, cat, NULL)
40 #define TOTAL_AVERAGE_PATCH_F(head, type, member, cat, fp) \
41 __TOTAL_AVERAGE_PATCH(head, type, member, cat, fp)
43 #define GET_RANK(real_rank, rank, node_cur, head, type, member) do {\
44 type *node_prev;\
45 rank++;\
46 if (node_cur->list.prev != head) {\
47 node_prev = list_entry(node_cur->member.prev,\
48 type, member);\
49 if (g_line == SELECT) { \
50 if (node_cur->chgline < node_prev->chgline)\
51 real_rank = rank;\
52 } else {\
53 if (node_cur->cnt < node_prev->cnt)\
54 real_rank = rank;\
55 } \
56 } else\
57 real_rank = rank; } while (0)
59 /* It's not good to show the emails by text on Internet.
60 * Convert email address to coded one.
61 * This will convert all '@' to " () " and '.' to " ! ".
63 char nospamstr[256];
64 static char *anti_spam(char *orig)
66 char *p = nospamstr;
68 if (g_nospam && orig) {
69 /* this loop just cp the name */
70 while (*orig != '\0' && *orig != '<') {
71 *p = *orig;
72 orig++;
73 p++;
75 /* this loop convert email address */
76 while (*orig != '\0') {
77 if (*orig == '@') {
78 *p = ' ';
79 p++;
80 *p = '(';
81 p++;
82 *p = ')';
83 p++;
84 *p = ' ';
85 } else if (*orig == '.') {
86 *p = ' ';
87 p++;
88 *p = '!';
89 p++;
90 *p = ' ';
91 } else {
92 *p = *orig;
94 orig++;
95 p++;
97 *p = '\0';
98 return nospamstr;
99 } else {
100 return orig;
104 static void print_child(struct list_head *head)
106 struct person *per_cur;
107 int rank = 0, real_rank = 0;
109 list_for_each_entry(per_cur, head, list) {
110 GET_RANK(real_rank, rank, per_cur, head,
111 struct person, list);
112 if (g_line == SELECT)
113 printf(" +--No.%d\t%-64s %llu\n", real_rank,
114 anti_spam(per_cur->name), per_cur->chgline);
115 else
116 printf(" +--No.%d\t%-64s %d\n", real_rank,
117 anti_spam(per_cur->name), per_cur->cnt);
121 static void print_dir(struct list_head *head)
123 struct directory *dir_cur;
124 int rank = 0, real_rank = 0;
126 list_for_each_entry(dir_cur, head, list) {
127 GET_RANK(real_rank, rank, dir_cur, head,
128 struct directory, list);
129 printf(" +--No.%d\t%-64s %d\n", real_rank,
130 dir_cur->name, dir_cur->cnt);
134 void print_all(struct list_head *head)
136 struct company *com_cur;
137 int rank = 0, real_rank = 0;
139 TOTAL_AVERAGE_PATCH(head, struct company, list, "company");
141 list_for_each_entry(com_cur, head, list) {
142 GET_RANK(real_rank, rank, com_cur, head,
143 struct company, list);
144 if (g_line == SELECT)
145 printf("No.%d\t%s: %llu(%.2lf%%)\n", real_rank,
146 com_cur->name, com_cur->chgline,
147 (double)com_cur->chgline*100/total_num);
148 else
149 printf("No.%d\t%s: %d(%.2lf%%)\n", real_rank,
150 com_cur->name, com_cur->cnt,
151 (double)com_cur->cnt*100/total_num);
152 print_child(com_cur->child);
156 void print_com_int(struct list_head *head)
158 struct company *com_cur;
159 int rank = 0, real_rank = 0;
161 printf("The following is the statistic about which source \
162 directory venders contribute most.\nIt implies each vender's interest area \
163 in Linux kernel.\n");
164 TOTAL_AVERAGE_PATCH(head, struct company, list, "company");
166 list_for_each_entry(com_cur, head, list) {
167 GET_RANK(real_rank, rank, com_cur, head,
168 struct company, list);
169 if (g_line == SELECT)
170 printf("No.%d\t%s: %llu(%.2lf%%)\n", real_rank,
171 com_cur->name, com_cur->chgline,
172 (double)com_cur->chgline*100/total_num);
173 else
174 printf("No.%d\t%s: %d(%.2lf%%)\n", real_rank,
175 com_cur->name, com_cur->cnt,
176 (double)com_cur->cnt*100/total_num);
177 print_dir(com_cur->dir);
181 void print_com_rank(struct list_head *head, unsigned int topx)
183 int rank = 0, real_rank = 0;
184 struct company *com_cur;
185 unsigned long long int topx_total = 0;
187 /* output all if topx is 0 */
188 if (!topx)
189 topx = 0xffffffff; /* evenif it can be larger on 64-bit box */
191 TOTAL_AVERAGE_PATCH(head, struct company, list, "company");
193 /* get topx's total number */
194 list_for_each_entry(com_cur, head, list) {
195 GET_RANK(real_rank, rank, com_cur, head,
196 struct company, list);
197 if (real_rank > topx)
198 break;
199 if (g_line == SELECT)
200 topx_total += com_cur->chgline;
201 else
202 topx_total += com_cur->cnt;
205 if (topx != 0xffffffff)
206 printf("TOP%d companies contribute %.2lf%% of total.\n",
207 topx, topx_total?(double)topx_total*100/total_num:0);
209 /* init the following var again */
210 real_rank = 0;
211 rank = 0;
213 list_for_each_entry(com_cur, head, list) {
214 GET_RANK(real_rank, rank, com_cur, head,
215 struct company, list);
216 if (real_rank > topx)
217 break;
218 if (g_line == SELECT)
219 printf("No.%d\t %-32s %llu(%.2lf%%)\t\n", real_rank,
220 com_cur->name, com_cur->chgline,
221 (double)com_cur->chgline*100/total_num);
222 else
223 printf("No.%d\t %-32s %d(%.2lf%%)\t\n", real_rank,
224 com_cur->name, com_cur->cnt,
225 (double)com_cur->cnt*100/total_num);
229 void print_com_detail(struct list_head *head, char *com_name)
231 int exist = 0, rank = 0, real_rank = 0;
232 struct company *com_cur;
234 TOTAL_AVERAGE_PATCH(head, struct company, list, "company");
236 list_for_each_entry(com_cur, head, list) {
237 GET_RANK(real_rank, rank, com_cur, head,
238 struct company, list);
239 if (strcasestr(com_cur->name, com_name)) {
240 exist = 1;
241 printf("----------------------------------------\n");
242 if (g_line == SELECT)
243 printf("No.%d\t%-64s %llu(%.2lf%%)\n",
244 real_rank,
245 com_cur->name, com_cur->chgline,
246 (double)com_cur->chgline*100/total_num);
247 else
248 printf("No.%d\t%-64s %d(%.2lf%%)\n", real_rank,
249 com_cur->name, com_cur->cnt,
250 (double)com_cur->cnt*100/total_num);
251 print_child(com_cur->child);
255 if (!exist)
256 printf("[WARNING]: company \"%s\" not exist.\n", com_name);
259 void print_per_detail(struct list_head *head, char *per_name)
261 int rank = 0, exist = 0, real_rank = 0;
262 struct person *per_cur;
264 TOTAL_AVERAGE_PATCH(head, struct person, list, "person");
266 list_for_each_entry(per_cur, head, list) {
267 GET_RANK(real_rank, rank, per_cur, head,
268 struct person, list);
269 if (strcasestr(per_cur->name, per_name)) {
270 exist = 1;
271 if (g_line == SELECT)
272 printf("No.%d\t%-64s %llu\n", real_rank,
273 anti_spam(per_cur->name), per_cur->chgline);
274 else
275 printf("No.%d\t%-64s %d\n", real_rank,
276 anti_spam(per_cur->name), per_cur->cnt);
280 if (!exist) {
281 printf("[WARNING]: Author \"%s\" does not exist.\n", per_name);
282 printf(" Please give me correct author name or"\
283 " mail address.\n");
287 void print_per_rank(struct list_head *head, unsigned int topx)
289 int real_rank = 0, rank = 0;
290 struct person *per_cur;
291 unsigned long long int topx_total = 0;
293 /* output all if topx is 0 */
294 if (!topx)
295 topx = 0xffffffff; /* evenif it can be larger on 64-bit box */
297 TOTAL_AVERAGE_PATCH(head, struct person, list, "person");
299 /* get topx's total number */
300 list_for_each_entry(per_cur, head, list) {
301 GET_RANK(real_rank, rank, per_cur, head,
302 struct person, list);
303 if (real_rank > topx)
304 break;
305 if (g_line == SELECT)
306 topx_total += per_cur->chgline;
307 else
308 topx_total += per_cur->cnt;
311 if (topx != 0xffffffff)
312 printf("TOP%d people contribute %.2lf%% of total.\n",
313 topx, topx_total?(double)topx_total*100/total_num:0);
315 /* init the following var again */
316 real_rank = 0;
317 rank = 0;
319 list_for_each_entry(per_cur, head, list) {
320 GET_RANK(real_rank, rank, per_cur, head,
321 struct person, list);
322 if (real_rank > topx)
323 break;
324 if (g_line == SELECT)
325 printf("No.%d\t %-64s %llu(%.2lf%%)\t@%-32s@%s\n",
326 real_rank,
327 anti_spam(per_cur->name), per_cur->chgline,
328 (double)per_cur->chgline*100/total_num,
329 per_cur->parent->name, per_cur->country);
330 else
331 printf("No.%d\t %-64s %d(%.2lf%%)\t@%-32s@%s\n",
332 real_rank,
333 anti_spam(per_cur->name), per_cur->cnt,
334 (double)per_cur->cnt*100/total_num,
335 per_cur->parent->name, per_cur->country);
339 void print_per_cnt(struct list_head *head, char *country)
341 struct person *per_cur;
342 int country_total = 0;
343 int country_people = 0;
345 TOTAL_AVERAGE_PATCH(head, struct person, list, "person");
347 list_for_each_entry(per_cur, head, list) {
348 if (!strcasestr(per_cur->country, country))
349 continue;
350 country_people++;
351 if (g_line == SELECT)
352 country_total += per_cur->chgline;
353 else
354 country_total += per_cur->cnt;
357 printf("%d(%.2lf%%) %s people contribute %d(%.2lf%%) %s.\n\n",
358 country_people, country_people?(double)country_people*100/node_cnt:0, country,
359 country_total, country_total?(double)country_total*100/total_num:0,
360 statistics_msg);
361 /* Declare who @country means
362 printf("(NOTE: \"%s\" means who ethnically belongs to %s descent and many different\
363 nationalities are represented)\n\n", country, country);
365 list_for_each_entry(per_cur, head, list) {
366 if (!strcasestr(per_cur->country, country))
367 continue;
368 if (g_line == SELECT)
369 printf("%-64s %llu(%.2lf%%)\t%-32s\n",
370 anti_spam(per_cur->name), per_cur->chgline,
371 (double)per_cur->chgline*100/total_num,
372 per_cur->parent->name);
373 else
374 printf("%-64s %d(%.2lf%%)\t%-32s\n",
375 anti_spam(per_cur->name), per_cur->cnt,
376 (double)per_cur->cnt*100/total_num,
377 per_cur->parent->name);
381 static int file2file(const char *input, char *output, const char *mode)
383 FILE *fp_o, *fp_i;
384 char *line = NULL;
385 size_t len = 0;
386 ssize_t read;
388 fp_i = fopen(input, "r");
389 if (!fp_i) {
390 printf("[ERROR]: Can not open %s.\n", input);
391 return 1;
394 fp_o = fopen(output, mode);
395 if (!fp_o) {
396 printf("[ERROR]: Can not open %s.\n", output);
397 fclose(fp_i);
398 return 1;
401 while ((read = getline(&line, &len, fp_i)) != -1)
402 fputs(line, fp_o);
404 if (line)
405 free(line);
406 fclose(fp_o);
407 fclose(fp_i);
409 return 0;
412 static void print_child_html(struct list_head *head, FILE *fp_o)
414 struct person *per_cur;
415 int rank = 0, real_rank = 0;
416 char *new_str, *new_str_tmp;
418 list_for_each_entry(per_cur, head, list) {
419 GET_RANK(real_rank, rank, per_cur, head,
420 struct person, list);
421 str_conv(anti_spam(per_cur->name), &new_str_tmp, "<", "&lt;");
422 str_conv(new_str_tmp, &new_str, ">", "&gt;");
423 if (g_line == SELECT)
424 fprintf(fp_o, "<li>No.%d\t%-64s%llu</li>",
425 real_rank, new_str, per_cur->chgline);
426 else
427 fprintf(fp_o, "<li>No.%d\t%-64s%d</li>",
428 real_rank, new_str, per_cur->cnt);
429 if (new_str)
430 free(new_str);
431 if (new_str_tmp)
432 free(new_str_tmp);
436 int print_html(struct list_head *head, char *output)
438 struct company *com_cur;
439 int rank = 0, real_rank = 0;
440 FILE *fp_o;
442 if (file2file(html_tmpl_h, output, "w"))
443 return 1;
445 fp_o = fopen(output, "a");
446 if (!fp_o) {
447 printf("[ERROR]: Can not open %s.\n", output);
448 return 1;
451 fprintf(fp_o, "<pre>\n");
452 TOTAL_AVERAGE_PATCH_F(head, struct company, list, "companies", fp_o);
453 list_for_each_entry(com_cur, head, list) {
454 GET_RANK(real_rank, rank, com_cur, head,
455 struct company, list);
456 if (g_line == SELECT)
457 fprintf(fp_o,
458 "<li>No.%d\t%-32s%llu(%.2lf%%)",
459 real_rank, com_cur->name, com_cur->chgline,
460 (double)com_cur->chgline*100/total_num);
461 else
462 fprintf(fp_o,
463 "<li>No.%d\t%-32s%d(%.2lf%%)",
464 real_rank, com_cur->name, com_cur->cnt,
465 (double)com_cur->cnt*100/total_num);
466 fprintf(fp_o, "\t\t<ul>");
467 print_child_html(com_cur->child, fp_o);
468 fprintf(fp_o, "\t\t</ul>");
469 fprintf(fp_o, "\t</li>");
471 fprintf(fp_o, "</pre>\n");
472 fclose(fp_o);
474 if (file2file(html_tmpl_f, output, "a"))
475 return 1;
477 return 0;
480 static void print_child_html_cnty(struct list_head *head, FILE *fp_o)
482 struct person *per_cur;
483 int rank = 0, real_rank = 0;
484 char *new_str, *new_str_tmp;
486 list_for_each_entry(per_cur, head, cnt_list) {
487 GET_RANK(real_rank, rank, per_cur, head,
488 struct person, cnt_list);
489 str_conv(anti_spam(per_cur->name), &new_str_tmp, "<", "&lt;");
490 str_conv(new_str_tmp, &new_str, ">", "&gt;");
491 if (g_line == SELECT)
492 fprintf(fp_o, "<li>No.%d\t%-64s%llu</li>",
493 real_rank, new_str, per_cur->chgline);
494 else
495 fprintf(fp_o, "<li>No.%d\t%-64s%d</li>",
496 real_rank, new_str, per_cur->cnt);
497 if (new_str)
498 free(new_str);
499 if (new_str_tmp)
500 free(new_str_tmp);
504 int print_cnty(struct list_head *head, char *output)
506 struct country *cnt_cur;
507 int rank = 0, real_rank = 0;
508 FILE *fp_o;
510 if (file2file(html_tmpl_h, output, "w"))
511 return 1;
513 fp_o = fopen(output, "a");
514 if (!fp_o) {
515 printf("[ERROR]: Can not open %s.\n", output);
516 return 1;
519 fprintf(fp_o, "<pre>\n");
520 TOTAL_AVERAGE_PATCH_F(head, struct country, list, "countries", fp_o);
521 list_for_each_entry(cnt_cur, head, list) {
522 GET_RANK(real_rank, rank, cnt_cur, head,
523 struct country, list);
524 if (g_line == SELECT)
525 fprintf(fp_o,
526 "<li>No.%d\t%-32s%llu(%.2lf%%)",
527 real_rank, cnt_cur->name, cnt_cur->chgline,
528 (double)cnt_cur->chgline*100/total_num);
529 else
530 fprintf(fp_o,
531 "<li>No.%d\t%-32s%d(%.2lf%%)",
532 real_rank, cnt_cur->name, cnt_cur->cnt,
533 (double)cnt_cur->cnt*100/total_num);
534 fprintf(fp_o, "\t\t<ul>");
535 print_child_html_cnty(cnt_cur->child, fp_o);
536 fprintf(fp_o, "\t\t</ul>");
537 fprintf(fp_o, "\t</li>");
539 fprintf(fp_o, "</pre>\n");
540 fclose(fp_o);
542 if (file2file(html_tmpl_f, output, "a"))
543 return 1;
545 return 0;
548 static void print_dir_html(struct list_head *head, FILE *fp_o)
550 struct directory *dir_cur;
551 int rank = 0, real_rank = 0;
552 char *new_str, *new_str_tmp;
554 list_for_each_entry(dir_cur, head, list) {
555 GET_RANK(real_rank, rank, dir_cur, head,
556 struct directory, list);
557 str_conv(dir_cur->name, &new_str_tmp, "<", "&lt;");
558 str_conv(new_str_tmp, &new_str, ">", "&gt;");
559 fprintf(fp_o, "<li>No.%d\t%-64s%d</li>",
560 real_rank, new_str, dir_cur->cnt);
561 if (new_str)
562 free(new_str);
563 if (new_str_tmp)
564 free(new_str_tmp);
568 int print_com_int_html(struct list_head *head, char *output)
570 struct company *com_cur;
571 int rank = 0, real_rank = 0;
572 FILE *fp_o;
574 if (file2file(html_tmpl_h, output, "w"))
575 return 1;
577 fp_o = fopen(output, "a");
578 if (!fp_o) {
579 printf("[ERROR]: Can not open %s.\n", output);
580 return 1;
583 fprintf(fp_o, "<pre>\n");
584 fprintf(fp_o, "The following is the statistic about which source \
585 directory venders contribute most.\nIt implies each vender's interest area \
586 in Linux kernel.\n");
587 TOTAL_AVERAGE_PATCH_F(head, struct company, list, "company", fp_o);
589 list_for_each_entry(com_cur, head, list) {
590 GET_RANK(real_rank, rank, com_cur, head,
591 struct company, list);
592 if (g_line == SELECT)
593 fprintf(fp_o,
594 "<li>No.%d\t%-32s%llu(%.2lf%%)",
595 real_rank, com_cur->name, com_cur->chgline,
596 (double)com_cur->chgline*100/total_num);
597 else
598 fprintf(fp_o,
599 "<li>No.%d\t%-32s%d(%.2lf%%)",
600 real_rank, com_cur->name, com_cur->cnt,
601 (double)com_cur->cnt*100/total_num);
602 fprintf(fp_o, "\t\t<ul>");
603 print_dir_html(com_cur->dir, fp_o);
604 fprintf(fp_o, "\t\t</ul>");
605 fprintf(fp_o, "\t</li>");
607 fprintf(fp_o, "</pre>\n");
608 fclose(fp_o);
610 if (file2file(html_tmpl_f, output, "a"))
611 return 1;
613 return 0;
616 int print_cnty_int(struct list_head *head, char *output)
618 struct country *cnt_cur;
619 int rank = 0, real_rank = 0;
620 FILE *fp_o;
622 if (file2file(html_tmpl_h, output, "w"))
623 return 1;
625 fp_o = fopen(output, "a");
626 if (!fp_o) {
627 printf("[ERROR]: Can not open %s.\n", output);
628 return 1;
631 fprintf(fp_o, "<pre>\n");
632 TOTAL_AVERAGE_PATCH_F(head, struct country, list, "countries", fp_o);
634 list_for_each_entry(cnt_cur, head, list) {
635 GET_RANK(real_rank, rank, cnt_cur, head,
636 struct country, list);
637 fprintf(fp_o,
638 "<li>No.%d\t%-32s%d(%.2lf%%)",
639 real_rank, cnt_cur->name, cnt_cur->cnt,
640 (double)cnt_cur->cnt*100/total_num);
641 fprintf(fp_o, "\t\t<ul>");
642 print_dir_html(cnt_cur->dir, fp_o);
643 fprintf(fp_o, "\t\t</ul>");
644 fprintf(fp_o, "\t</li>");
646 fprintf(fp_o, "</pre>\n");
647 fclose(fp_o);
649 if (file2file(html_tmpl_f, output, "a"))
650 return 1;
652 return 0;
655 void print_longtail(struct list_head *head, int num)
657 int amount = 0, total = 0;
658 unsigned long long int tail_total = 0;
659 struct person *per_cur;
661 TOTAL_AVERAGE_PATCH(head, struct person, list, "person");
663 list_for_each_entry(per_cur, head, list) {
664 if (g_line == SELECT) {
665 if (per_cur->chgline <= num) {
666 amount++;
667 tail_total = tail_total + per_cur->chgline;
669 total = total + per_cur->chgline;
670 } else {
671 if (per_cur->cnt <= num) {
672 amount++;
673 tail_total = tail_total + per_cur->cnt;
675 total = total + per_cur->cnt;
679 printf("We have a long tail:\n");
681 printf("There are %d people who committed less than %d %s.\n",
682 amount, num, statistics_msg);
683 printf("But their contribution is about %llu%% of total.\n",
684 tail_total?tail_total*100/total:0);
687 int print_sql(struct list_head *head, char *output, char *rls)
689 struct company *com_cur;
690 FILE *fp_o;
691 int ret = 0;
693 fp_o = fopen(output, "w");
694 if (!fp_o) {
695 printf("[ERROR]: Can not open %s.\n", output);
696 return 1;
699 fprintf(fp_o, "<?php\n");
701 list_for_each_entry(com_cur, head, list) {
702 char *com_name;
703 struct person *per_cur;
705 if (sql_str(com_cur->name, &com_name) != 0) {
706 ret = 1;
707 goto out;
709 fprintf(fp_o,"$sql_mid .=\'(NULL, \\\'%s\\\', \\\'1\\\', "
710 "\\\'%s\\\', \\\'%d\\\', "
711 "\\\'%llu\\\', NULL), \';\n",
712 com_name, rls,
713 com_cur->cnt, com_cur->chgline);
715 list_for_each_entry(per_cur, com_cur->child, list) {
716 char *per_name;
717 if (sql_str(per_cur->name, &per_name) != 0) {
718 ret = 1;
719 free(com_name);
720 goto out;
722 fprintf(fp_o,"$sql_mid .=\'(NULL, \\\'%s\\\', "
723 "\\\'0\\\', \\\'%s\\\', \\\'%d\\\', "
724 "\\\'%llu\\\', \\\'%s\\\'), \';\n",
725 per_name, rls,
726 per_cur->cnt, per_cur->chgline, com_name);
727 free(per_name);
729 free(com_name);
732 fprintf(fp_o, "?>\n");
733 out:
734 fclose(fp_o);
735 return ret;
737 #endif