9 #define __TOTAL_AVERAGE_PATCH(head, type, member, cat, fp) do {\
13 list_for_each_entry(cur, head, member) { \
15 if (g_line == SELECT) \
16 total_num = total_num + cur->chgline;\
18 total_num = total_num + cur->cnt; \
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",\
25 fprintf(fp, "Averagely, every %s committed %u %s.\n\n", \
26 cat, total_num?total_num/node_cnt:0, statistics_msg); \
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",\
32 printf("Averagely, every %s committed %u %s.\n\n", \
33 cat, total_num?total_num/node_cnt:0, statistics_msg); \
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 {\
46 if (node_cur->list.prev != head) {\
47 node_prev = list_entry(node_cur->member.prev,\
49 if (g_line == SELECT) { \
50 if (node_cur->chgline < node_prev->chgline)\
53 if (node_cur->cnt < node_prev->cnt)\
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 " ! ".
64 static char *anti_spam(char *orig
)
68 if (g_nospam
&& orig
) {
69 /* this loop just cp the name */
70 while (*orig
!= '\0' && *orig
!= '<') {
75 /* this loop convert email address */
76 while (*orig
!= '\0') {
85 } else if (*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
);
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
);
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
);
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 */
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
)
199 if (g_line
== SELECT
)
200 topx_total
+= com_cur
->chgline
;
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 */
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
)
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
);
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
)) {
241 printf("----------------------------------------\n");
242 if (g_line
== SELECT
)
243 printf("No.%d\t%-64s %llu(%.2lf%%)\n",
245 com_cur
->name
, com_cur
->chgline
,
246 (double)com_cur
->chgline
*100/total_num
);
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
);
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
)) {
271 if (g_line
== SELECT
)
272 printf("No.%d\t%-64s %llu\n", real_rank
,
273 anti_spam(per_cur
->name
), per_cur
->chgline
);
275 printf("No.%d\t%-64s %d\n", real_rank
,
276 anti_spam(per_cur
->name
), per_cur
->cnt
);
281 printf("[WARNING]: Author \"%s\" does not exist.\n", per_name
);
282 printf(" Please give me correct author name or"\
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 */
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
)
305 if (g_line
== SELECT
)
306 topx_total
+= per_cur
->chgline
;
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 */
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
)
324 if (g_line
== SELECT
)
325 printf("No.%d\t %-64s %llu(%.2lf%%)\t@%-32s@%s\n",
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
);
331 printf("No.%d\t %-64s %d(%.2lf%%)\t@%-32s@%s\n",
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
))
351 if (g_line
== SELECT
)
352 country_total
+= per_cur
->chgline
;
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,
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
))
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
);
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
)
388 fp_i
= fopen(input
, "r");
390 printf("[ERROR]: Can not open %s.\n", input
);
394 fp_o
= fopen(output
, mode
);
396 printf("[ERROR]: Can not open %s.\n", output
);
401 while ((read
= getline(&line
, &len
, fp_i
)) != -1)
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
, "<", "<");
422 str_conv(new_str_tmp
, &new_str
, ">", ">");
423 if (g_line
== SELECT
)
424 fprintf(fp_o
, "<li>No.%d\t%-64s%llu</li>",
425 real_rank
, new_str
, per_cur
->chgline
);
427 fprintf(fp_o
, "<li>No.%d\t%-64s%d</li>",
428 real_rank
, new_str
, per_cur
->cnt
);
436 int print_html(struct list_head
*head
, char *output
)
438 struct company
*com_cur
;
439 int rank
= 0, real_rank
= 0;
442 if (file2file(html_tmpl_h
, output
, "w"))
445 fp_o
= fopen(output
, "a");
447 printf("[ERROR]: Can not open %s.\n", output
);
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
)
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
);
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");
474 if (file2file(html_tmpl_f
, output
, "a"))
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
, "<", "<");
490 str_conv(new_str_tmp
, &new_str
, ">", ">");
491 if (g_line
== SELECT
)
492 fprintf(fp_o
, "<li>No.%d\t%-64s%llu</li>",
493 real_rank
, new_str
, per_cur
->chgline
);
495 fprintf(fp_o
, "<li>No.%d\t%-64s%d</li>",
496 real_rank
, new_str
, per_cur
->cnt
);
504 int print_cnty(struct list_head
*head
, char *output
)
506 struct country
*cnt_cur
;
507 int rank
= 0, real_rank
= 0;
510 if (file2file(html_tmpl_h
, output
, "w"))
513 fp_o
= fopen(output
, "a");
515 printf("[ERROR]: Can not open %s.\n", output
);
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
)
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
);
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");
542 if (file2file(html_tmpl_f
, output
, "a"))
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
, "<", "<");
558 str_conv(new_str_tmp
, &new_str
, ">", ">");
559 fprintf(fp_o
, "<li>No.%d\t%-64s%d</li>",
560 real_rank
, new_str
, dir_cur
->cnt
);
568 int print_com_int_html(struct list_head
*head
, char *output
)
570 struct company
*com_cur
;
571 int rank
= 0, real_rank
= 0;
574 if (file2file(html_tmpl_h
, output
, "w"))
577 fp_o
= fopen(output
, "a");
579 printf("[ERROR]: Can not open %s.\n", output
);
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
)
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
);
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");
610 if (file2file(html_tmpl_f
, output
, "a"))
616 int print_cnty_int(struct list_head
*head
, char *output
)
618 struct country
*cnt_cur
;
619 int rank
= 0, real_rank
= 0;
622 if (file2file(html_tmpl_h
, output
, "w"))
625 fp_o
= fopen(output
, "a");
627 printf("[ERROR]: Can not open %s.\n", output
);
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
);
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");
649 if (file2file(html_tmpl_f
, output
, "a"))
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
) {
667 tail_total
= tail_total
+ per_cur
->chgline
;
669 total
= total
+ per_cur
->chgline
;
671 if (per_cur
->cnt
<= num
) {
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
;
693 fp_o
= fopen(output
, "w");
695 printf("[ERROR]: Can not open %s.\n", output
);
699 fprintf(fp_o
, "<?php\n");
701 list_for_each_entry(com_cur
, head
, list
) {
703 struct person
*per_cur
;
705 if (sql_str(com_cur
->name
, &com_name
) != 0) {
709 fprintf(fp_o
,"$sql_mid .=\'(NULL, \\\'%s\\\', \\\'1\\\', "
710 "\\\'%s\\\', \\\'%d\\\', "
711 "\\\'%llu\\\', NULL), \';\n",
713 com_cur
->cnt
, com_cur
->chgline
);
715 list_for_each_entry(per_cur
, com_cur
->child
, list
) {
717 if (sql_str(per_cur
->name
, &per_name
) != 0) {
722 fprintf(fp_o
,"$sql_mid .=\'(NULL, \\\'%s\\\', "
723 "\\\'0\\\', \\\'%s\\\', \\\'%d\\\', "
724 "\\\'%llu\\\', \\\'%s\\\'), \';\n",
726 per_cur
->cnt
, per_cur
->chgline
, com_name
);
732 fprintf(fp_o
, "?>\n");