add debug
[kps.git] / patch_sta.h
blob9820d22238cf9a32b94e4b643288d1fc8c35519d
1 #ifndef INC_PATCH_STA
2 #define INC_PATCH_STA
4 #include "list.h"
5 #include "string.h"
6 #include "conv.h"
8 #define OPT_OK 0
9 #define OPT_ERROR 2
10 #define SELECT 1
11 #define NSELECT 0
13 /* Some systems do not define EXIT_*, despite otherwise supporting C89 */
14 #ifndef EXIT_SUCCESS
15 #define EXIT_SUCCESS
16 #endif
18 /* FIXME -- WCN : Currently not support corporation statistic */
19 #ifdef CONFIG_CORP
20 struct corp {
21 char *name;
22 int cnt;
23 struct company *child;
24 struct corp *next;
25 struct corp *pre;
27 #endif
29 struct company {
30 struct list_head list;
31 char *name;
32 int cnt;
33 unsigned long long int chgline;
34 #ifdef CONFIG_CORP
35 struct corp *parent;
36 #endif
37 struct list_head *child;
38 struct list_head *dir;
41 struct country {
42 struct list_head list;
43 char *name;
44 int cnt;
45 unsigned long long int chgline;
46 struct list_head *child;
47 struct list_head *dir;
50 struct person {
51 struct list_head list;
52 struct list_head cnt_list;
53 char *name;
54 struct company *parent;
55 struct country *nation;
56 int cnt;
57 unsigned long long int chgline;
58 char *country;
61 /* to find out employers interest in which area */
62 struct directory {
63 struct list_head list;
64 char *name;
65 int cnt;
66 /* dummy field */
67 unsigned long long int chgline;
70 struct list_head *cnty_list;
72 /* The name this program was run with. */
73 char *program_name;
74 char *filename_i;
75 int g_help = NSELECT;
76 int g_all = NSELECT;
77 int g_comtop = NSELECT;
78 int g_com = NSELECT;
79 int g_tail = NSELECT;
80 int g_person = NSELECT;
81 int g_nation = NSELECT;
82 int g_pertop = NSELECT;
83 int g_html = NSELECT;
84 int g_cnty = NSELECT;
85 int g_sql = NSELECT;
86 int g_notconv = NSELECT;
87 int g_line = NSELECT;
88 int g_interest = NSELECT;
89 int g_nat_interest = NSELECT;
90 /* Other statistics, such as: Reported-by, Reviewed-by, Tested-by, Acked-by */
91 int g_other = NSELECT;
92 int g_warning = NSELECT;
93 int g_nospam = NSELECT;
94 double p_comtop;
95 char *p_com;
96 char *p_person;
97 char *p_nation;
98 double p_pertop;
99 double p_tail;
100 char *p_html;
101 char *p_cnty;
102 char *p_nat_interest;
103 char *p_sql;
104 char *p_other;
105 char *p_rls="linux"; /* set it to "linux" as default */
106 const char *html_tmpl_h = "./html_tmpl_h.html";
107 const char *html_tmpl_f = "./html_tmpl_f.html";
108 const char *tmp_author_file = "./tmp_author";
109 const char *BUGREPORT = "ellre923@gmail.com";
111 /* what kind of statistics */
112 int other;
113 #define OTHER_REPORT 0
114 #define OTHER_REVIEW 1
115 #define OTHER_TEST 2
116 #define OTHER_ACK 3
117 #define OTHER_SOF 4
119 const char *str_line = "changed lines";
120 const char *str_patch = "patch sets";
121 const char *str_report = "Reported-by";
122 const char *str_review = "Reviewed-by";
123 const char *str_test = "Tested-by";
124 const char *str_ack = "Acked-by";
125 const char *str_sof = "Signed-off-by";
126 char statistics_msg[32];
128 #define STRUCT_INIT(type) (type *)malloc(sizeof(type))
130 #define NODE_INIT(type, node) do { \
131 node = STRUCT_INIT(type); \
132 if (node == NULL) { \
133 printf("[ERROR]: No enough mem\n"); \
134 return 1; \
136 memset(node, 0, sizeof(type)); \
137 INIT_LIST_HEAD(&(node->list)); } while (0)
139 #define NODE_SET_NAME(node, str) do {\
140 node->name = (char *)malloc(strlen(str)+1);\
141 if (node->name == NULL) {\
142 printf("[ERROR]: No enough mem\n"); \
143 return 1; \
145 memcpy(node->name, str, strlen(str)+1); } while (0)
147 #define NODE_SET_CNT(node, str) do {\
148 node->country = (char *)malloc(strlen(str)+1);\
149 if (node->country == NULL) {\
150 printf("[ERROR]: No enough mem\n"); \
151 return 1; \
153 memcpy(node->country, str, strlen(str)+1); } while (0)
155 #define LIST_RESORT(head, list_node, type, member) do {\
156 struct list_head *list_cur; \
157 type *node = list_entry(list_node, type, member); \
158 int cnt = node->cnt; \
159 int chgline = node->chgline; \
160 list_for_each(list_cur, head) { \
161 type *node_cur = list_entry(list_cur, type, member); \
162 if (g_line == SELECT) { \
163 if (node_cur->chgline <= chgline) \
164 break; \
165 } else { \
166 if (node_cur->cnt <= cnt) \
167 break; \
170 if (list_node != list_cur) \
171 list_move_tail(list_node, list_cur); } while (0)
173 /* Update the child's info of the com. */
174 static void update_child(struct person *per_cur, unsigned long long int chgline)
176 per_cur->cnt++;
177 per_cur->chgline += chgline;
178 LIST_RESORT(per_cur->parent->child, &(per_cur->list),
179 struct person, list);
182 /* Update the dir list of nation */
183 static int update_cnty_dir(struct country *cnty, struct list_head *dir_list)
185 struct directory *dir_current, *dir, *dir_current2;
187 if (list_empty(dir_list))
188 return 0;
190 list_for_each_entry(dir_current, dir_list, list) {
191 list_for_each_entry(dir_current2, cnty->dir, list)
192 if (strcasestr(dir_current2->name, dir_current->name))
193 break;
194 if (&dir_current2->list == cnty->dir) {
195 /* new directory */
196 NODE_INIT(struct directory, dir);
197 NODE_SET_NAME(dir, dir_current->name);
198 dir->cnt = 1;
199 list_add_tail(&(dir->list), cnty->dir);
200 } else {
201 struct list_head *cur_dir_list = &(dir_current2->list);
202 dir_current2->cnt++;
203 LIST_RESORT(cnty->dir, cur_dir_list, struct directory, list);
206 return 0;
209 /* Update the person's info in the global per list. */
210 static void update_per(struct person *per_cur, struct list_head *per_list,
211 unsigned long long int chgline,
212 struct list_head *dir_list)
214 per_cur->cnt++;
215 per_cur->chgline += chgline;
216 LIST_RESORT(per_list, &(per_cur->list), struct person, list);
218 per_cur->nation->cnt++;
219 per_cur->nation->chgline += chgline;
220 update_cnty_dir(per_cur->nation, dir_list);
221 LIST_RESORT(per_cur->nation->child, &(per_cur->cnt_list),
222 struct person, cnt_list);
223 LIST_RESORT(cnty_list, &(per_cur->nation->list), struct country, list);
227 * new_per: Create and add a per node to com's child list. If the global per
228 * list has no this per node, create and add the same node to global
229 * per list.
230 * @com_cur: The com node which should link the new per node.
231 * @per_list: The global per list.
232 * @per_name: The person's name.
233 * @chgline: The commit's changed lines.
234 * @dir_list: The patch's dir list used for nation dir list update.
235 * Return: 0 - successful
236 * 1 - not successful
238 static int new_per(struct company *com_cur, struct list_head *per_list,
239 char *per_name, unsigned long long int chgline,
240 struct list_head *dir_list)
242 struct person *per;
243 char *per_cnt = NULL;
244 char *mail_name = NULL;
245 char *name = NULL;
246 struct person *per_current;
247 struct country *cnty;
249 /* create a new person node which will be added to the com */
250 NODE_INIT(struct person, per);
251 NODE_SET_NAME(per, per_name);
252 conv_cnt(per_name, &per_cnt);
253 NODE_SET_CNT(per, per_cnt);
254 per->parent = com_cur;
255 per->cnt++;
256 per->chgline += chgline;
258 /* find the nation in global list */
259 list_for_each_entry(cnty, cnty_list, list)
260 if (memcmp(cnty->name, per_cnt, strlen(per_cnt)+1)
261 == 0)
262 break;
263 if (&(cnty->list) == cnty_list) {
264 /* create a new nation */
265 NODE_INIT(struct country, cnty);
266 NODE_SET_NAME(cnty, per_cnt);
267 /* alloc mem for child list */
268 cnty->child = STRUCT_INIT(struct list_head);
269 INIT_LIST_HEAD(cnty->child);
270 /* init dir list */
271 cnty->dir = STRUCT_INIT(struct list_head);
272 INIT_LIST_HEAD(cnty->dir);
273 list_add_tail(&(cnty->list), cnty_list);
275 per->nation = cnty;
277 /* add the person to company's per_list */
278 list_add_tail(&(per->list), com_cur->child);
279 LIST_RESORT(com_cur->child, &(per->list), struct person, list);
281 /* get mail from author info */
282 if (mail_from_per(&mail_name, per_name) < 0)
283 return 1;
284 /* get person's name */
285 if (name_from_per(&name, per_name) < 0)
286 return 1;
287 /* lookup person in global per list */
288 list_for_each_entry(per_current, per_list, list)
289 if (strcasestr(per_current->name, mail_name))
290 break;
291 else if ((g_warning == SELECT) &&
292 strcasestr(per_current->name, name)) {
293 char *mail_from = NULL, *mail_to = NULL;
294 mail_from_per(&mail_from, per_current->name);
295 mail_from_per(&mail_to, per_name);
296 fprintf(stderr,
297 "WARNING: %s and %s might same person.\n",
298 per_current->name, per_name);
299 fprintf(stderr, "Patch number is %d.\n",per_current->cnt);
300 fprintf(stderr,
301 "Suggestion: CONV_PER(\"%s\", \"%s\", NULL),\n",
302 mail_from, mail_to);
303 free(mail_from);
304 free(mail_to);
306 if (&per_current->list == per_list) {
307 /* before using the pointer again, set it to NULL */
308 per = NULL;
309 NODE_INIT(struct person, per);
310 NODE_SET_NAME(per, per_name);
311 NODE_SET_CNT(per, per_cnt);
312 per->parent = com_cur;
313 per->cnt++;
314 per->chgline += chgline;
315 per->nation = cnty;
316 /* add the person to nation's per_list */
317 list_add_tail(&(per->cnt_list), cnty->child);
318 LIST_RESORT(cnty->child, &(per->cnt_list), struct person, cnt_list);
319 /* update the nation list */
320 cnty->cnt++;
321 cnty->chgline += chgline;
322 update_cnty_dir(cnty, dir_list);
323 LIST_RESORT(cnty_list, &(cnty->list), struct country, list);
324 /* add the person to global per_list */
325 list_add_tail(&(per->list), per_list);
326 LIST_RESORT(per_list, &(per->list), struct person, list);
327 } else {
328 update_per(per_current, per_list, chgline, dir_list);
331 if (mail_name)
332 free(mail_name);
333 if (name)
334 free(name);
335 free(per_cnt);
336 return 0;
339 int new_com(struct list_head *com_list, struct list_head *per_list,
340 char *com_name, char *per_name, struct list_head *dir_list,
341 unsigned long long int chgline)
343 struct company *com;
344 struct directory *dir_current, *dir;
346 /* create a new company node */
347 NODE_INIT(struct company, com);
348 NODE_SET_NAME(com, com_name);
349 /* alloc mem for child list */
350 com->child = STRUCT_INIT(struct list_head);
351 INIT_LIST_HEAD(com->child);
352 list_add_tail(&(com->list), com_list);
354 new_per(com, per_list, per_name, chgline, dir_list);
356 /* add directory distribute infor */
357 com->dir = STRUCT_INIT(struct list_head);
358 INIT_LIST_HEAD(com->dir);
359 if (!list_empty(dir_list)) {
360 list_for_each_entry(dir_current, dir_list, list) {
361 NODE_INIT(struct directory, dir);
362 NODE_SET_NAME(dir, dir_current->name);
363 dir->cnt = 1;
364 list_add_tail(&(dir->list), com->dir);
368 /* update the company list */
369 com->cnt++;
370 com->chgline += chgline;
371 LIST_RESORT(com_list, &(com->list), struct company, list);
373 return 0;
376 int update_com(struct company *com_cur, struct list_head *com_list,
377 struct list_head *per_list, char *per_name,
378 struct list_head *dir_list, unsigned long long int chgline)
380 struct person *per_current;
381 char *mail_name = NULL;
382 struct directory *dir_current, *dir, *dir_current2;
384 /* get mail from person's name */
385 if (mail_from_per(&mail_name, per_name) < 0)
386 return 1;
387 /* search for this person in com's child */
388 list_for_each_entry(per_current, com_cur->child, list)
389 if (strcasestr(per_current->name, mail_name))
390 break;
391 if (&per_current->list == com_cur->child) {
392 /* the person is new, we add it to list */
393 if (new_per(com_cur, per_list, per_name, chgline, dir_list))
394 return 1;
395 } else {
396 /* the person is exist, we update the info of person and com */
397 update_child(per_current, chgline);
398 /* find the person in global per list and update */
399 list_for_each_entry(per_current, per_list, list)
400 if (strcasestr(per_current->name, mail_name))
401 break;
402 if (&per_current->list == per_list)
403 return 1;
404 else
405 update_per(per_current, per_list, chgline, dir_list);
408 if (list_empty(dir_list))
409 goto no_dir;
411 /* update directory distribute infor */
412 list_for_each_entry(dir_current, dir_list, list) {
413 list_for_each_entry(dir_current2, com_cur->dir, list)
414 if (strcasestr(dir_current2->name, dir_current->name))
415 break;
416 if (&dir_current2->list == com_cur->dir) {
417 /* new directory */
418 NODE_INIT(struct directory, dir);
419 NODE_SET_NAME(dir, dir_current->name);
420 dir->cnt = 1;
421 list_add_tail(&(dir->list), com_cur->dir);
422 } else {
423 struct list_head *cur_dir_list = &(dir_current2->list);
424 dir_current2->cnt++;
425 LIST_RESORT(com_cur->dir, cur_dir_list, struct directory, list);
429 no_dir:
430 /* update the person's company info */
431 com_cur->cnt++;
432 com_cur->chgline += chgline;
433 LIST_RESORT(com_list, &(com_cur->list), struct company, list);
435 if (mail_name)
436 free(mail_name);
437 return 0;
439 #endif